Java多线程,判断其他线程是否结束的三种方法
方法1:thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。
View Code
工人类
司机类
View Code
比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
t.join(); //调用join方法,等待线程t执行完毕
t.join(1000); //等待 t 线程,等待时间是1000毫秒。
1 public class TestJoin implements Runnable { 2 3 4 public static void main(String[] sure) throws InterruptedException { 5 Thread t = new Thread(new TestJoin()); 6 long start = System.currentTimeMillis(); 7 t.start(); 8 t.join(1000);//等待线程t 1000毫秒 9 System.out.println(System.currentTimeMillis()-start);//打印出时间间隔 10 System.out.println("Main finished");//打印主线程结束 11 } 12 13 @Override 14 public void run() { 15 // synchronized (currentThread()) { 16 for (int i = 1; i <= 5; i++) { 17 try { 18 sleep(1000);//睡眠5秒,循环是为了方便输出信息 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 System.out.println("睡眠" + i); 23 } 24 System.out.println("TestJoin finished");//t线程结束 25 } 26 //} 27 }
方法2:通过同步类CountDownLatch判断当前线程的线程组中活动线程的数目,为0时其他线程运行完毕。
同步辅助类:
CountDownLatch是一个同步辅助类,在jdk5中引入,它允许一个或多个线程等待其他线程操作完成之后才执行。
实现原理 :
CountDownLatch是通过计数器的方式来实现,计数器的初始值为线程的数量。每当一个线程完成了自己的任务之后,就会对计数器减1,当计数器的值为0时,表示所有线程完成了任务,此时等待在闭锁上的线程才继续执行,从而达到等待其他线程完成任务之后才继续执行的目的。
CountDownLatch实践
司机和工人,工人必须等到司机来了才能装货上车,司机必须得等到所有工人把货物装上车了之后才能把车开走。
同步类代码:
1 import java.util.concurrent.CountDownLatch; 2 3 public class Worker implements Runnable { 4 5 private String workerCode; 6 7 private CountDownLatch startLatch; 8 private CountDownLatch latch; 9 10 Worker(CountDownLatch startLatch, CountDownLatch latch, String workerCode) { 11 this.startLatch = startLatch; 12 this.latch = latch; 13 this.workerCode = workerCode; 14 } 15 16 public void run() { 17 try { 18 startLatch.await(); 19 doWork(); 20 latch.countDown(); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 } 25 26 private void doWork() { 27 System.out.println("Worker " + workerCode + " is loading goods..."); 28 } 29 }
1 import java.util.concurrent.CountDownLatch; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 public class Driver { 6 public static void main(String[] args) throws InterruptedException { 7 CountDownLatch startLatch = new CountDownLatch(1); 8 CountDownLatch latch = new CountDownLatch(10); 9 ExecutorService executor = Executors.newFixedThreadPool(10); 10 11 for(int i=0; i<10; i++) { 12 executor.execute(new Worker(startLatch, latch, "worker" + i)); 13 } 14 15 System.out.println("Driver is here."); 16 17 startLatch.countDown(); 18 19 System.out.println("Workers get to work."); 20 21 latch.await(); 22 23 System.out.println("Driver is ready to go."); 24 25 executor.shutdown(); 26 } 27 }
方法3:通过java.util.concurrent.Executors中的方法创建一个线程池,用这个线程池来启动线程。启动所有要启动的线程后,执行线程池的shutdown()方法,即在所有线程执行完毕后关闭线程池。然后通过线程池的isTerminated()方法,判断线程池是否已经关闭。线程池成功关闭,就意味着所有线程已经运行完毕了。
线程池方法示例代码:
1 import java.util.concurrent.ExecutorService; 2 import java.util.concurrent.Executors; 3 4 public class Test { 5 6 public static void main(String args[]) throws InterruptedException { 7 ExecutorService exe = Executors.newFixedThreadPool(50); 8 for (int i = 1; i <= 5; i++) { 9 exe.execute(new SubThread(i)); 10 } 11 exe.shutdown(); 12 while (true) { 13 if (exe.isTerminated()) { 14 System.out.println("结束了!"); 15 break; 16 } 17 Thread.sleep(200); 18 } 19 } 20 }
一个思路:
给所有的线程加上同步(同一个锁),主线程在启动其他所有线程后wait()。每个线程运行结束后,执行notify()方法。设定一个值为其他线程数量的int计数器count,写一个while循环,循环条件为count-->0,循环内容为wait()。则所有线程运行结束后正好while循环结束。 致命缺陷:如果几个线程同时运行结束,有可能在主线程还没运行时,已经执行了好几次notify()方法。如果这样的话,while循环就永远不会结束了,主线程一直wait()下去。