Java线程池的个人总结(四)

9 线程池实现原理

9.1 线程池组成部分

线程池管理器

工作线程

任务队列

任务

9.2 Executor家族

Java线程池的个人总结(四)

Executor:它是一个顶层接口,其他接口以及类都i继承或实现于它,包含以下方法:

void execute(Runnable command);

ExecutorService:它继承于Executor,是Executor的子接口,在接口内部增加了一些新的方法,例如第6小节讲到的几个方法

Executors:这个类是一个工具类,里面包含一些创建线程池的方法

9.3 线程池实现任务复用的原理

利用相同线程执行不同任务

源码分析

<code>public void execute(Runnable 

command

) { // 判断任务是否为空,为空就抛出异常

if

(

command

== null) throw new NullPointerException(); int c = ctl.get(); // 如果当前线程数小于核心线程数,就增加Worker

if

(workerCountOf(c) < corePoolSize) { //

command

就是任务,点击addWorker方法 // 第二个参数用于判断当前线程数是否小于核心线程数

if

(addWorker(

command

,

true

))

return

; c = ctl.get(); } // 此时线程数大于等于核心线程数 // 判断线程池是不是正在运行并将任务放到工作队列中

if

(isRunning(c) && workQueue.offer(

command

)) { // 再次检查线程状态 int recheck = ctl.get(); // 如果线程不是正在运行的,就删除掉任务并且拒绝

if

(! isRunning(recheck) && remove(

command

)) reject(

command

);

else

if

(workerCountOf(recheck) == 0) //这里用于避免已经提交的任务没有线程进行执行 addWorker(null,

false

); } // 如果任务无法添加或者大于最大线程数就拒绝任务

else

if

(!addWorker(

command

,

false

)) reject(

command

);}/<code>

因为要查看的是Worker所以进入到addWorker()方法后点击Worker类查看runWorker()方法

<code>

w

=

new

Worker(firstTask);private

final

class

Worker

extends

AbstractQueuedSynchronizer

implements

Runnablefinal

void

runWorker(Worker

w)

{

Thread

wt

=

Thread.currentThread();

//

获取到任务

Runnable

task

=

w.firstTask;

w.firstTask

=

null

;

w.unlock();

//

allow

interrupts

boolean

completedAbruptly

=

true

;

try

{

//

只要任务不为空或者能够获取到任务就执行下面的方法

while

(task

!=

null

||

(task

=

getTask())

!=

null

)

{

w.lock();

if

((runStateAtLeast(ctl.get(),

STOP)

||

(Thread.interrupted()

&&

runStateAtLeast(ctl.get(),

STOP)))

&&

!wt

.isInterrupted())

wt.interrupt();

try

{

beforeExecute(wt,

task);

Throwable

thrown

=

null

;

try

{

//

task是一个Runnable类型,调用run()方法就是运行线程

task.run();

}

catch

(RuntimeException

x)

{

thrown

=

x;

throw

x;

}

catch

(Error

x)

{

thrown

=

x;

throw

x;

}

catch

(Throwable

x)

{

thrown

=

x;

throw

new

Error(x);

}

finally

{

afterExecute(task,

thrown);

}

}

finally

{

task

=

null

;

w.completedTasks++;

w.unlock();

}

}

completedAbruptly

=

false

;

}

finally

{

processWorkerExit(w,

completedAbruptly);

}}

/<code>

总结:核心原理就是获取到task,如果task不为空就调用run()方法,这样就实现了线程的复用,达到让相同的线程执行不同任务的目的。

10 线程池状态

RUNNING:接受新任务并处理排队任务

SHUTDOWN:不接受新的任务但是处理排队任务

STOP:不接受新的任务,也不处理排队的任务,并中断正在执行的任务,就是调用shutdownNow()带来的效果

TIDYING:中文意思是整洁,意思就是说任务都已经终止,workerCount为零时,线程会转换到TIDYING状态,并将运行terminate()钩子方法

TERMINATED:terminate()运行完成


11 使用线程池的注意点

避免任务的堆积(堆积容易产生内存溢出)

避免线程数过多增加(缓存线程池会导致线程数过度增加)

排查线程泄漏(线程已经执行完毕却无法被回收)


分享到:


相關文章: