手写连笔王万能驱动-便携式wifi

countdown下载
2023年4月4日发(作者:多玩魔盒好用吗)

Java控制线程执⾏顺序的⼏种⽅法

叙述

通常情况下,线程的执⾏顺序都是随机的,哪个获取到CPU的时间⽚,哪个就获得执⾏的机会。不过实际的项⽬中有时我们会有需要不同的

线程顺序执⾏的需求。借助⼀些java中的线程阻塞和同步机制,我们往往也可以控制多个线程的执⾏顺序。

⽅法有很多种,本篇⽂章介绍⼏种常⽤的。

解决⽅案

利⽤threadjoin实现线程顺序执⾏

⽅法的可以实现如下的效果,就是挂起调⽤join⽅法的线程的执⾏,直到被调⽤的线程执⾏结束。听起来有点绕,举个例⼦解释

下:

假设有t1,t2两个线程,如果在t2的线程流程中调⽤了,那么t2线程将会停⽌执⾏,等待t1执⾏结束后才会继续执⾏。

很显然,利⽤这个机制,我们可以控制线程的执⾏顺序,看下⾯的例⼦:

publicclassControlThreadDemo{

publicstaticvoidmain(String[]args){

ThreadpreviousThread=tThread();

for(inti=0;i<10;i++){

ThreadJoinDemothreadJoinDemo=newThreadJoinDemo(previousThread);

();

previousThread=threadJoinDemo;

}

n("主线程执⾏完毕");

}

}

publicclassThreadJoinDemoextendsThread{

privateThreadpreviousThread;

publicThreadJoinDemo(Threadthread){

usThread=thread;

}

publicvoidrun(){

try{

n("线程:"+tThread().getName()+"等待"+e());

();

}catch(InterruptedExceptione){

tackTrace();

}

n(tThread().getName()+"开始执⾏");

}

}

运⾏结果:

从执⾏结果可以很容易理解,程序运⾏起来之后,⼀共11个线程排好队等着执⾏,排在最前⾯的是main线程,然后依次是t0,t1…。

利⽤CountDownLatch控制线程的执⾏顺序

还是先说下CountDownLatch的⽤法,CountDownLatch是⼀个同步⼯具类,它允许⼀个或多个线程⼀直等待,直到其他线程执⾏完后

再执⾏。借⽤⼀张经典的图:

CountDownLatch提供两个核⼼的⽅法,countDown和await,后者可以阻塞调⽤它的线程,⽽前者每调⽤⼀次,计数器减去1,当计数

器减到0的时候,阻塞的线程被唤醒继续执⾏。

场景1

先看⼀个例⼦,在这个例⼦中,主线程会等有若⼲个⼦线程执⾏完毕之后再执⾏,不过这若⼲个⼦线程之间的执⾏顺序是随机的。

publicclassControlThreadDemo{

publicstaticvoidmain(String[]args)throwsInterruptedException{

CountDownLatchcountDownLatch=newCountDownLatch(5);

Listworkers=te(()->newThread(newCountDownDemo(countDownLatch))).limit(5).collect(());

h(Thread::start);

();

n("主线程执⾏完毕");

}

}

publicclassCountDownDemoimplementsRunnable{

privateCountDownLatchcountDownLatch;

publicCountDownDemo(CountDownLatchlatch){

ownLatch=latch;

}

@Override

publicvoidrun(){

n("线程"+tThread().getName()+"开始执⾏");

own();

}

}

输出,

这种场景在实际项⽬中有需要的场景,⽐如我之前看过⼀个案例,⼤概的场景是说需要下载⼀个⼤⽂件,开启多个线程分别下载⽂件的⼀部

分,然后有⼀个线程最后拼接所有的⽂件。我们可以考虑使⽤CountDownLatch来控制并发,使拼接的线程放在最后执⾏。

场景2

这个案例带你了解下利⽤CountDownLatch控制⼀组线程⼀起执⾏。就好像在运动场上,教练的发令枪⼀响,所有运动员⼀起跑。我们⼀

般在模拟线程并发执⾏的时候会⽤到这种场景。

我们把场景1的代码稍微改造⼀下,

publicclassControlThreadDemo{

publicstaticvoidmain(String[]args)throwsInterruptedException{

CountDownLatchreadyLatch=newCountDownLatch(5);

CountDownLatchrunningLatchWait=newCountDownLatch(1);

CountDownLatchcompleteLatch=newCountDownLatch(5);

Listworkers=te(()->newThread(newCountDownDemo2(readyLatch,runningLatchWait,completeLatch))).limit(5).collect(Collectors

h(Thread::start);

();//等待发令

own();//发令

();//等所有⼦线程执⾏完

n("主线程执⾏完毕");

}

}

publicclassCountDownDemo2implementsRunnable{

privateCountDownLatchreadyLatch;

privateCountDownLatchrunningLatchWait;

privateCountDownLatchcompleteLatch;

publicCountDownDemo2(CountDownLatchreadyLatch,CountDownLatchrunningLatchWait,CountDownLatchcompleteLatch){

atch=readyLatch;

gLatchWait=runningLatchWait;

teLatch=completeLatch;

}

@Override

publicvoidrun(){

own();

try{

();

n("线程"+tThread().getName()+"开始执⾏");

}catch(InterruptedExceptione){

tackTrace();

}finally{

own();

}

}

}

场景3

到这⾥,可能很多⼈会想问,利⽤CountDownLatch能做到像前⾯控制多个线程按照⼀个固定的先后顺序执⾏吗?

⾸先我要说,⽤CountDownLatch实现这种场景确实不多见,不过也不是不可以做。请继续看场景3。

publicclassControlThreadDemo{

publicstaticvoidmain(String[]args)throwsInterruptedException{

CountDownLatchfirst=newCountDownLatch(1);

CountDownLatchprev=first;

for(inti=0;i<10;i++){

CountDownLatchnext=newCountDownLatch(1);

newCountDownDemo3(prev,next).start();

prev=next;

}

own();

}

}

publicclassCountDownDemo3extendsThread{

privateCountDownLatchprev;

privateCountDownLatchnext;

publicCountDownDemo3(CountDownLatchprev,CountDownLatchnext){

=prev;

=next;

}

@Override

publicvoidrun(){

try{

();

(1000);//模拟线程执⾏耗时

n("线程"+tThread().getName()+"开始执⾏");

}catch(InterruptedExceptione){

tackTrace();

}finally{

own();

}

}

}

输出,

代码也不难理解,for循环⾥把10个线程串联起来,排好队等着执⾏。排在最前⾯的线程t1在等first这个计数器countDown,然后t1开始

执⾏,执⾏完调⽤⾃⼰的next计数器countDown以唤醒下⼀个,依次类推。

利⽤newSingleThreadExecutor控制线程的执⾏顺序

java的Executors线程池平时⼯作中⽤得很多了,JAVA通过Executors提供了四种线程池,单线程化线程池

(newSingleThreadExecutor)、可控最⼤并发数线程池(newFixedThreadPool)、可回收缓存线程池(newCachedThreadPool)、⽀持定

时与周期性任务的线程池(newScheduledThreadPool)。

顾名思义,newSingleThreadExecutor线程池只有⼀个线程。它存在的意义就在于控制线程执⾏的顺序,保证任务的执⾏顺序和提交顺序

⼀致。其实保证顺序执⾏的原理也很简单,因为总是只有⼀个线程处理任务队列上的任务,先提交的任务必将被先处理。

废话不多说,上代码。

publicstaticvoidmain(String[]args)throwsInterruptedException{

finalExecutorServiceexecutorService=gleThreadExecutor();

for(inti=0;i<5;i++){

finalintindex=i;

e(newRunnable(){

@Override

publicvoidrun(){

tThread().setName("thread-"+index);

n("线程:"+tThread().getName()+"开始执⾏");

try{

(1000);

}catch(InterruptedExceptione){

tackTrace();

}

}

});

}

ermination(30,S);

wnNow();

}

输出,

更多推荐

countdown下载