`
Action-人生
  • 浏览: 104920 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

判断线程池中的线程是否全部执行完毕

阅读更多
https://www.cnblogs.com/stonefeng/p/5967451.html
在使用多线程的时候有时候我们会使用 java.util.concurrent.Executors的线程池,当多个线程异步执行的时候,我们往往不好判断是否线程池中所有的子线程都已经执行完毕,但有时候这种判断却很有用,例如我有个方法的功能是往一个文件异步地写入内容,我需要在所有的子线程写入完毕后在文件末尾写“---END---”及关闭文件流等,这个时候我就需要某个标志位可以告诉我是否线程池中所有的子线程都已经执行完毕,我使用这种方式来判断。

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 }

这种解决方案虽然可以达到目的但是性能差到没朋友,我更倾向于使用第一种方案。
现在我们有了更优雅的第三种方案,它的执行性能也不错。

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 }
分享到:
评论

相关推荐

    C#判断线程池中所有的线程是否已经完成

    线程池中的线程通常用于执行异步任务,因此在某些场景下,我们需要判断线程池中所有的线程是否已经完成工作。这个问题可以通过注册一个等待单个对象(RegisterWaitForSingleObject)并配合定期检查线程池状态来解决...

    Java 判断线程池所有任务是否执行完毕的操作

    在 Java 中判断线程池所有任务是否执行完毕是非常重要的操作,我们需要使用 `shutdown()` 和 `isTerminated()` 方法来确保所有任务都已经执行完毕。同时,我们还需要了解 Java 中的安全机制,以保护我们的应用程序。

    Java判断线程池线程是否执行完毕

    Java判断线程池线程是否执行完毕是Java多线程编程中的一种常见问题,当我们使用线程池来执行多个任务时,需要判断所有的子线程是否已经执行完毕,以便进行后续操作。下面我们将介绍两种解决方案:使用Semaphore和...

    多线程编程线程池

    任务执行完毕后,线程并不会立即销毁,而是返回到线程池中等待下一个任务。这种方式大大减少了频繁创建和销毁线程所带来的开销,提高了系统的整体性能。 #### 三、.NET中的线程池实现 在.NET框架中,线程池是由公共...

    JAVA主线程等待子线程执行完毕再执行[参照].pdf

    JAVA 中的线程控制是非常重要的一部分,而在实际开发中,我们经常会遇到需要主线程等待子线程执行完毕再执行的情况。这种情况下,我们可以使用两种方式来实现:主动式和被动式。 主动式 在主动式中,主线程会主动...

    java线程池概念.txt

    这里线程池线程大小还需要判断一次;前面的判断过程中并没有加锁,因此可能在execute方法判断的时候poolSize小于corePoolSize,而判断完之后,在其他线程中又向线程池提交了任务,就可能导致poolSize不小于...

    uThreadPool线程池示例(查找0-1亿之间的质数任务)

    6. 关闭线程池:所有任务执行完毕后,关闭线程池,释放资源。 在压缩包文件“线程池D7”中,可能包含了`uThreadPool`的源代码、示例程序、以及运行和测试所需的相关文件。通过查看这些文件,我们可以更深入地理解`...

    Java多线程–让主线程等待所有子线程执行完毕

    在主线程中,检查列表是否为空或线程是否都在运行,如果所有线程都完成了,就可以继续主线程的任务。 每种方法都有其适用场景,根据实际情况选择合适的方法。在处理大量并发任务时,合理地使用并发工具可以提高程序...

    线程分解详细

    在Java等支持多线程的编程语言中,我们可以创建并启动多个线程,每个线程执行不同的任务。 要实现这个需求,可以使用Java的`Thread`类或者`Runnable`接口。创建三个线程对象,分别为A、B、C,每个线程内部包含一个...

    qt5多线程pingIP地址(纯线程)

    - 管理线程生命周期,确保所有线程执行完毕后正确关闭。 这种设计模式在很多网络监控、服务器管理或者设备诊断的场景中都非常实用。通过Qt5的多线程和系统命令调用功能,我们可以构建出高效、易扩展的网络检测工具...

    python爬虫-08-主线程会等待子线程执行结束再结束.ev4.rar

    本教程重点讲解了在Python中如何处理主线程与子线程的关系,特别是主线程如何等待子线程执行完毕后再结束。 在Python中,多线程是一种并发执行的方式,可以提高程序的运行效率。`threading`模块提供了创建和管理...

    鱼刺类_线程池Ex的命令详解及框架构建-易语言

     获取线程池状态是否彻底空闲,也就是说任务是否全部执行完毕,可以作为后续投递任务完任务后的判断。 15. 取_线程池容量()  获取线程池的可执行的最小线程数量 16. 取_最大线程容量()  获取线程池中可执行的最大...

    检测线程状态

    - **终止(Terminated)**:线程执行完毕或被显式中断。 在Java中,可以使用`Thread.getState()`方法获取线程当前状态。 3. **Python中的线程状态** Python的`threading.Thread`对象没有直接提供线程状态,但...

    易语言-易语言真正的线程池简易实现

    1.通过一个主线程来监视是否有新任务,如果有新任务,则判断当前的线程数是否大于最大线程数,如果小于最大线程数则创建新线程,反之则加入线程队列等待执行。 2.当时间经过过长(1分钟,可手动设置)主线程会自动...

    多线程ping

    最后,等待所有线程执行完毕,收集并分析结果。 以下是一个简单的多线程ping Python代码示例: ```python import os import threading def ping_ip(ip): result = os.system('ping -c 1 ' + ip) # 在这里替换为...

    基于C++17实现的简易线程池源码(含超详细注释+知识说明文档).zip

    当主函数运行完时,线程池将销毁,执行析构函数,那么线程池就会关闭,不管等待队列里面是否存在线程,整个线程池将会关闭,那么等待队列里面的线程将无法执行。当我们提交一个空任务时,同时调用了`get`方法。`get...

    Java 多线程学习总结6

    - **终止(Terminated)**:run()方法执行完毕或抛出异常,线程结束。 3. **线程同步与互斥** - **synchronized**:通过关键字synchronized实现临界区保护,确保同一时刻只有一个线程访问共享资源。 - **...

    Java中线程死亡的几种情况实例分析

    在Java中,判断线程是否已经死亡,可以使用`Thread.isAlive()`方法。如果线程处于运行、就绪或阻塞状态,这个方法返回`true`;反之,如果线程处于新建或死亡状态,它将返回`false`。例如,在上述的`ThreadTest`示例...

Global site tag (gtag.js) - Google Analytics