java8 blockingqueue,Java8线程池——底层为LinkedBlockingQueue的ThreadPoolExecutor

线程池使用的一个例子

这里约定,细节在代码中注释说明,代码外正文的描述文字展示程序的大体流程。

int nThreads = 10;

ExecutorService exec = Executors.newFixedThreadPool(nThreads);

Runnable task = new Runnable(){

public void run(){

//do something

}

};

exec.execute(task);

这里的工厂方法newFixedThreadPool()初始化的是ThreadPoolExecutor实例,在线程池实现的工厂方法newSingleThreadExecutor()与newFixedThreadPool()一样构建底层为LinkedBlockingQueue的ThreadPoolExecutor。而newCachedThreadPool()初始化的是底层为SynchronousQueue的ThreadPoolExecutor实例。

public static ExecutorService newFixedThreadPool(int nThreads) {

return new ThreadPoolExecutor(nThreads, nThreads,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue());

}

ThreadPoolExecutor的execute()

任务到来执行execute()方法。

public void execute(Runnable command) {

if (command == null)

throw new NullPointerException();

/*

* Proceed in 3 steps:

* 执行过程分为三步:

*

* 1. If fewer than corePoolSize threads are running, try to

* start a new thread with the given command as its first

* task. The call to addWorker atomically checks runState and

* workerCount, and so prevents false alarms that would add

* threads when it shouldn't, by returning false.

*

* 1. 如果少于corePoolSize条线程在运行,那么试图启动一条新的线程,并且把当前的命令作

* 为这条线程将要执行的第一个任务。addWorker()方法原子性检查runState和workerCount

* 的状态,以防止不应该增加线程时添加了线程。

*

* 2. If a task can be successfully queued, then we still need

* to double-check whether we should have added a thread

* (because existing ones died since last checking) or that

* the pool shut down since entry into this method. So we

* recheck state and if necessary roll back the enqueuing if

* stopped, or start a new thread if there are none.

*

* 2. 如果一个任务成功入队,我们需要进行双重的校验,校验我们是否应该增加一个线程(因

* 为从上次校验之后存在的线程可能已经死掉了)或者检查线程池是否关闭了。所以需要再次

* 检验,如果需要进行回滚出队。或者,如果没有线程,就开始一条新的线程。

*

* 3. If we cannot queue task, then we try to add a new

* thread. If it fails, we know we are shut down or saturated

* and so reject the task.

*

* 3. 如果任务入队不成功,我们试图增加新的进程。仍旧失败的话,直接拒绝执行任务。

*/

int c = ctl.get();

//①

if (workerCountOf(c) < corePoolSize) {

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);

}

上面的execute()方法的源代码中注释的标号,对应着上面的英文注释,中文翻译在对应英文下面。先大体看流程,execute()方法执行新的任务,当一个任务到来后,做必要的校验,根据检验的不同结果,执行不同的逻辑实现。但是任务的执行都是通过addWorker()方法完成的,下面流程走的addWorker()方法中。

ThreadPoolExecutor的addWorker()

addWorker()方法代码片段

private boolean addWorker(Runnable firstTask, boolean core) {

....省略一些校验逻辑.....

boolean workerStarted = false;

boolean workerAdded = false;

Worker w = null;

try {

w = new Worker(firstTask);//①

final Thread t = w.thread;

if (t != null) {

final ReentrantLock mainLock = this.mainLock;//②

mainLock.lock();

try {

// Recheck while holding lock.

// Back out on ThreadFactory failure or if

// shut down before lock acquired.

int rs = runStateOf(ctl.get());

if (rs < SHUTDOWN ||

(rs == SHUTDOWN && firstTask == null)) {

if (t.isAlive()) // precheck that t is startable

throw new IllegalThreadStateException();

workers.add(w);

int s = workers.size();

if (s > largestPoolSize)

largestPoolSize = s;

workerAdded = true;

}

} finally {

mainLock.unlock();

}

if (workerAdded) {

t.start();//③

workerStarted = true;

}

}

} finally {

if (! workerStarted)

addWorkerFailed(w);

}

return workerStarted;

}

代码片段中有三点重要之处,分别标注了序号。

到来的任务,被封装在一个Worker的对象中。Worker对象字段thread赋值给变量t;

对线程池状态的参数设置和进一步的最终校验需要加锁,保证并发时的线程安全,和数据的一致性。

Thread变量t执行start()方法。

梳理上面的代码片段,到来的任务会被先封装Worker对象,然后Worker对象返回一个Thread对象,这个Thread对象最终执行。下面走到Worker类的源代码。

ThreadPoolExecutor的Worker类

//Worker的构造函数

Worker(Runnable firstTask) {

setState(-1); // inhibit interrupts until runWorker

this.firstTask = firstTask;

this.thread = getThreadFactory().newThread(this);

}

构造Worker对象时,Runnable任务作为当前线程的第一个任务赋值到firstTask,如果确实是第一个任务firstTask不为null,否则为null,然后去队列中取已经入队的任务。字段thread指向通过ThreadPoolExecutor中定义的线程工厂,生产的封装了Worker对象自己的线程。字段thread指向的对象执行start()方法(上面addWorker()方法代码中的③)时,底层调用的就是Worker对象的run()方法。

Worker类的run()方法

run()方法调用的是runWorker()方法。

public void run() {

runWorker(this);

}

Worker类的runWorker()方法

在runWorker()方法最重要的语句就是那一条while语句(下面代码中标识①的语句)。涉及如下三点:

如果任务task不为null,执行当前的task,此task是当前线程的第一个任务;

如果task为null,getTask()方法从任务队列中获取排队的任务进行执行;

while循环因为条件中getTask()方法会进行自旋,所以当任务队列中没有任务时,当前线程一直处于阻塞等待状态,利用阻塞队列也可以限时等待,这也是线程池中线程可以复用的原因。因为线程会一直等待队列中有任务。当然可以通过ThreadPoolExecutor的keepAliveTime字段对线程生存时间进行设定。

final 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 pool is stopping, ensure thread is interrupted;

// if not, ensure thread is not interrupted. This

// requires a recheck in second case to deal with

// shutdownNow race while clearing interrupt

if ((runStateAtLeast(ctl.get(), STOP) ||

(Thread.interrupted() &&

runStateAtLeast(ctl.get(), STOP))) &&

!wt.isInterrupted())

wt.interrupt();

try {

beforeExecute(wt, task);

Throwable thrown = null;

try {

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);

}

}

自此,完成了任务到来,提交给线程池,线程池创建线程或者复用等待中的线程执行任务。复用线程可以减少创建和销毁线程产生的开销,在高并发系统中线程池使用可以取得很好的性能效果。更多细节可以参考Java线程池ThreadPoolExecutor的实现和参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值