判断线程池中的线程是否所有执行完毕

转:html

判断线程池中的线程是否所有执行完毕

在使用多线程的时候有时候咱们会使用 java.util.concurrent.Executors的线程池,当多个线程异步执行的时候,咱们每每很差判断是否线程池中全部的子线程都已经执行完毕,但有时候这种判断却颇有用,例如我有个方法的功能是往一个文件异步地写入内容,我须要在全部的子线程写入完毕后在文件末尾写“---END---”及关闭文件流等,这个时候我就须要某个标志位能够告诉我是否线程池中全部的子线程都已经执行完毕,我使用这种方式来判断。java

复制代码
public class MySemaphore { public static void main(String[] args) throws IOException, InterruptedException { final File stream = new File("c:\\temp\\stonefeng\\stream.txt"); final OutputStream os = new FileOutputStream(stream); final OutputStreamWriter writer = new OutputStreamWriter(os); final Semaphore semaphore = new Semaphore(10); ExecutorService exec = Executors.newCachedThreadPool(); final long start = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { final int num = i; Runnable task = new Runnable() { @Override public void run() { try { semaphore.acquire(); writer.write(String.valueOf(num)+"\n"); semaphore.release(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }; exec.submit(task); } exec.shutdown(); while(true){ if(exec.isTerminated()){ writer.write("---END---\n"); writer.close(); System.out.println("全部的子线程都结束了!"); break; } Thread.sleep(1000); } final long end = System.currentTimeMillis(); System.out.println((end-start)/1000); } }
复制代码

当调用ExecutorService.shutdown方法的时候,线程池再也不接收任何新任务,但此时线程池并不会马上退出,直到添加到线程池中的任务都已经处理完成,才会退出。在调用shutdown方法后咱们能够在一个死循环里面用isTerminated方法判断是否线程池中的全部线程已经执行完毕,若是子线程都结束了,咱们就能够作关闭流等后续操做了。多线程

判断线程池中的线程是否所有执行完毕的另一种解决方案则是使用闭锁(CountDownLatch)来实现,CountDownLatch是一种灵活的闭锁实现,它能够使一个或多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化为一个正数,表示须要等待的事件数量。countDown方法递减计数器,表示有一个事件已经发生了,而await方法等待计数器达到零,即表示须要等待的事情都已经发生。能够使用闭锁来这样设计程序达到目的:
异步

复制代码
 1 public class CountDownLatchApproach {  2 public static void main(String[] args) throws IOException, InterruptedException {  3 final int nThreads = 10;  4 final CountDownLatch endGate = new CountDownLatch(nThreads);  5 final File stream = new File("c:\\temp\\stonefeng\\stream.txt");  6 final OutputStream os = new FileOutputStream(stream);  7 final OutputStreamWriter writer = new OutputStreamWriter(os);  8 ExecutorService exec = Executors.newCachedThreadPool();  9 for (int i = 0; i < nThreads; i++) { 10 final int num = i; 11 Runnable task = new Runnable() { 12  @Override 13 public void run() { 14 try { 15 writer.write(String.valueOf(num)+"\n"); 16 } catch (IOException e) { 17  e.printStackTrace(); 18 } finally { 19  endGate.countDown(); 20  } 21  } 22  }; 23  exec.submit(task); 24  } 25  endGate.await(); 26 writer.write("---END---\n"); 27  writer.close(); 28  } 29 }
复制代码

这种解决方案虽然能够达到目的可是性能差到没朋友,我更倾向于使用第一种方案。ide

如今咱们有了更优雅的第三种方案,它的执行性能也不错。post

复制代码
 1 public class MySemaphore {  2  3 public static void main(String[] args) throws IOException, InterruptedException {  4 final File stream = new File("c:\\temp\\stonefeng\\stream.txt");  5 final OutputStream os = new FileOutputStream(stream);  6 final OutputStreamWriter writer = new OutputStreamWriter(os);  7 final Semaphore semaphore = new Semaphore(10);  8 ExecutorService exec = Executors.newCachedThreadPool();  9 10 final long start = System.currentTimeMillis(); 11 for (int i = 0; i < 10000000; i++) { 12 final int num = i; 13 Runnable task = new Runnable() { 14  @Override 15 public void run() { 16 try { 17  semaphore.acquire(); 18 writer.write(String.valueOf(num)+"\n"); 19  semaphore.release(); 20 } catch (IOException e) { 21  e.printStackTrace(); 22 } catch (InterruptedException e) { 23  e.printStackTrace(); 24  } 25  } 26  }; 27  exec.submit(task); 28  } 29  exec.shutdown(); 30 exec.awaitTermination(1, TimeUnit.HOURS); 31 writer.write("---END---\n"); 32  writer.close(); 33 System.out.println("ËùÓеÄ×ÓÏ̶߳¼½áÊøÁË£¡"); 34 final long end = System.currentTimeMillis(); 35 System.out.println((end-start)/1000); 36  } 37 }
复制代码
相关文章
相关标签/搜索