场景如下:一共三个线程a,b,c,其中c需要用到a,b,执行的结果,应该怎么处理?
1)CountDownLatch,主线程中调用await方法,每个线程调用countdown
上面两种方法需要分别调用多次join或future的get方法,不太好,有一种方法是使用CountDownLatch类
认知CountDownLatch的方法:
await():阻塞主线程,直到countDownLatch的计数器减少到0的位置,
countDown:将当前的计数器减1
getCount:返回当前的数
思路如下:让a,b线程使用CountDowmLatch,然后执行countDownLatch的await方法
主类:
public static void main(String[] args) {
CountDownLatch countDownLaunch = new CountDownLatch(5);
for(int i=1;i<6;i++){
ThreadWithCountDownLatch threadWithCountDownLatch = new ThreadWithCountDownLatch(i*1000L,countDownLaunch,"THREAD"+i);
Thread thread = new Thread(threadWithCountDownLatch);
thread.start();
}
mainThreadWork();
try {
countDownLaunch.await();//下面的代码要等待所有的countDown的计数器为零再执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("all done");
}
线程类:
public class ThreadWithCountDownLatch implements Runnable{
long time;
CountDownLatch countDownLatch;
String name;
public ThreadWithCountDownLatch(long time,CountDownLatch countDownLatch,String name){
this.time=time;
this.countDownLatch = countDownLatch;
this.name=name;
}
@Override
public void run() {
try {
System.out.println(name+" start");
work(time);
System.out.println(name+" end");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
countDownLatch.countDown();
}
}
private void work(long time2) throws InterruptedException {
Thread.sleep(time2);
}
}
2)CyclicBarrier-每个线程中调用await,调用达到次数再一起放行
调用栅栏(计数器为5)的await,相当于告诉栅栏已经有一个线程到达栅栏,同时线程本身不再继续执行;当cyclicBarrier的await方法调用5次时,所有线程继续执行,同时触发栅栏的run方法
主类:
public static void main(String[] args) {
CyclicBarrier cylicBarrier = new CyclicBarrier(5,new Runnable() {
//栅栏动作,在计数器为零的时候执行
@Override
public void run() {//栅栏的await方法执行五次后会调用此处
// TODO Auto-generated method stub
System.out.println("all work done");
}
});
ExecutorService pool = Executors.newFixedThreadPool(5);
for(int i=1;i<6;i++){
pool.submit(new ThreadWithCyclicBarrier(i,cylicBarrier));
}
pool.shutdown();
System.out.println("last ");
}
线程类:
public class ThreadWithCyclicBarrier implements Runnable{
int id;
CyclicBarrier cyclicBarrier;
public ThreadWithCyclicBarrier(int id,CyclicBarrier cyclicBarrier){
this.id = id;
this.cyclicBarrier=cyclicBarrier;
}
@Override
public void run() {
System.out.println("thread"+id+" start");
try {
cyclicBarrier.await();//栅栏计数值为零后会继续执行
Thread.sleep(1000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread"+id+" end");
}
}
3)join方法实现
对a,b使用a.join()和b.join(); 然后下面使用c.start()
SubTThread subthread = new SubTThread("subthread");
SubTThread subthread2 = new SubTThread("subthread2");
SubTThread subthread3 = new SubTThread("subthread3");
Thread thread = new Thread(subthread);
Thread thread2 = new Thread(subthread2);
Thread thread3 = new Thread(subthread3);
thread.start();
thread2.start();
mainThreadWork();
System.out.println("wait subthread done");
try {
thread.join();
thread2.join();//当thread和thread2的run方法执行完毕后才会继续下面的代码
} catch (InterruptedException e) {
e.printStackTrace();
}
thread3.start();
System.out.println("all work done");
4)线程池submit线程返回Future,并调用future的get方法
使用线程池,线程池submit线程返回Future,并调用future的get方法.则get方法下的代码都需要等待调用了get方法的线程完全执行后再执行
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
SubTThreadByRun subthread = new SubTThreadByRun("subthread");
SubTThreadByRun subthread2 = new SubTThreadByRun("subthread2");
Thread thread = new Thread(subthread);
Thread thread2 = new Thread(subthread2);
ThreadByCall threadByCall = new ThreadByCall("call1");
Future future1 = pool.submit(thread);
Future future2 = pool.submit(thread2);
Future future3 = pool.submit(threadByCall);
mainThreadWork();
try {
future1.get();
future2.get();
String str = (String) future3.get();//下面的代码需要等待thread1/thread2和threadByCall 执行完毕后执行下面的代码
System.out.println("得到结果:"+str);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
SubTThreadByRun subthread3 = new SubTThreadByRun("subthread3");
Thread thread3 = new Thread(subthread3);
thread3.start();
System.out.println("all work done");
pool.shutdown();//关闭线程池
}
四种实现方式比较
join--适用于少量线程
线程池submit+future.get--适用于实际使用的线程数量不定,且所有线程执行完毕
CountDownLatch--设置线程数,每个线程结尾使用countDown()方法减值,主线程中调用await方法来阻塞,当数据减为0时,主线程继续执行,适用于实际使用线程数量固定
栅栏--多个线程都执行到某个点暂停,然后再一起开始,并且增加栅栏的run方法
new CyclicBarrier(5,new Runnable());每个线程执行到CyclicBarrier.await方法,线程会暂停,当await方法执行5次时,所有线程继续运行,并且执行cyclicBarrier的runner的run方法