Java线程池复用机制

2019-10-23  本文已影响0人  周_0717

        线程复用的实质就是在Tread内的Runnable的run()方法中不断的获取任务,执行任务。

        线程池内将保留核心线程数量的死循环线程,其余线程在没有任务时在超时间后若再无任务则销毁(run()方法执行结束)。

任务获取:

ThreadPoolExecutor.getTask()

        这个方法内主要做3件事情:①检查线程池状态;②判断是否支持任务等待超时(timed);③跟据timed选择对应方法,从BlockingQueue中获取任务。

        在第三步中涉及到BlockingQueue.poll(long timeout, TimeUnit unit)和BlockingQueue#take()两个方法,两个方法都会尝试阻塞当前线程直到被唤醒,差别在于第一个方法在到达等待时间后会自动唤醒,第二个方法只能主动唤醒。

BlockingQueue.poll(long timeout, TimeUnit unit)->Condition.awaitNanos(long nanosTimeout)->LockSupport.parkNanos(Object blocker, long nanos)->Unsafe.park(boolean b,long nanos)

BlockingQueue.take()->Condition.await()->LockSupport.park(Object blocker)->Unsafe.park(boolean b,long nanos)

执行任务:

ThreadPoolExecutor.runWorker(Worker w)

        上述方法由Worker.run()调用,当上述方法执行完毕同时Worker.run()也将执行完毕,对应当Thread将被销毁。其中当Worker.firstTask为Worker创建时传入的任务,所以在复用时为null,因此当ThreadPoolExecutor.getTask()返回null,线程结束。

唤醒线程:

        当通过ThreadPoolExecutor.execute(Runnable command)方法传入任务时,若存活线程数已超过核心线程数(少于则直接新建Worker),并且线程池已处于运行状态(否则尝试通过新建Worker启动线程池),此时会去调用BlockingQueue.offer(E e)方法,将任务放入BlockingQueue之中,并调用Condition.signal()方法唤醒一个之前阻塞的线程(LockSupport.unpark(Thread thread))。

上一篇下一篇

猜你喜欢

热点阅读