JAVA进阶----主线程等待子线程各种方案比较(转)

创建线程以及管理线程池基本理解 
参考原文链接:http://www.oschina.net/question/12_11255?sort=time

一、创建一个简单的java线程 
在 Java 语言中,一个最简单的线程如下代码所示:

Java代码  

  1. Runnable runnable = new Runnable(){
  2. public void run(){
  3. System.out.println("Run");
  4. }
  5. }

可通过下面一行代码来启动这个线程: 
new Thread(runnable).start(); 
这是一个再简单不过的例子了,但如果你有许多需要长时间运行的任务同时执行,并需要等所有的这些线程都执行完毕,还想得到一个返回值,那么这就有点小小难度了。但 Java 已经有解决方案给你,那就是 Executors ,一个简单的类可以让你创建线程池和线程工厂。

二、Executors创建线程池 
一个线程池使用类 ExecutorService 的实例来表示,通过 ExecutorService 你可以提交任务,并进行调度执行。下面列举一些你可以通过 Executors 类来创建的线程池的类型:

1.Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,代码:

Java代码  

  1. Executors.newSingleThreadExecutor()

2.Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,代码:

Java代码  

  1. Executors.newCachedThreadPool()

3.Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,代码:

Java代码  

  1. Executors.newFixedThreadPool()

4.Scheduled Thread Pool : 用来调度即将执行的任务的线程池,代码:

Java代码  

  1. Executors.newScheduledThreadPool()

5.Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:

Java代码  

  1. Executors.newSingleThreadScheduledExecutor()

三、主线程等待子线程结束各种方式 
一旦你创建了一个线程池,你就可以往池中通过不同的方法提交执行任务,可提交 Runnable 或者 Callable 到线程池中,该方法返回一个 Future 实例表示任务的状态,如果你提交一个 Runnable ,那么如果任务完成后 Future 对象返回 null。

例如,你编写下面的 Callable:

Java代码  

  1. private final class StringTask extends Callable<String>{
  2. public String call(){
  3. //Long operations
  4. return "Run";
  5. }
  6. }

如果你想使用4个线程来执行这个任务10次,那么代码如下: 
ExecutorService pool = Executors.newFixedThreadPool(4);

for(int i = 0; i < 10; i++){ 
   pool.submit(new StringTask()); 
}

但你必须手工的关闭线程池来结束所有池中的线程:

pool.shutdown();

如果你不这么做,JVM 并不会去关闭这些线程;另外你可以使用 shutdownNow() 的方法来强制关闭线程池,那么执行中的线程也会被中断,所有尚未被执行的任务也将不会再执行。

但这个例子中,你无法获取任务的执行状态,因此我们需要借助 Future 对象:

下面的例子同时可以阻塞主线程等待子线程完成,但是该方式,如果阻塞的第一个线程很久,可能其他线程已经执行完了,很多情况不太适用

Java代码  

  1. ExecutorService pool = Executors.newFixedThreadPool(4);
  2. List<Future<String>> futures = new ArrayList<Future<String>>(10);
  3. for(int i = 0; i < 10; i++){
  4. futures.add(pool.submit(new StringTask()));
  5. }
  6. for(Future<String> future : futures){
  7. String result = future.get();
  8. //Compute the result
  9. }
  10. pool.shutdown();

不过这段代码稍微有点复杂,而且有不足的地方。如果第一个任务耗费非常长的时间来执行,然后其他的任务都早于它结束,那么当前线程就无法在第一个任务结束之前获得执行结果,但是别着急,Java 为你提供了解决方案——CompletionService。

一个 CompletionService 就是一个服务,用以简化等待任务的执行结果,实现的类是 ExecutorCompletionService,该类基于 ExecutorService,因此我们可试试下面的代码:

Java代码  

  1. ExecutorService threadPool = Executors.newFixedThreadPool(4);
  2. CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);
  3. for(int i = 0; i < 10; i++){
  4. pool.submit(new StringTask());
  5. }
  6. for(int i = 0; i < 10; i++){
  7. String result = pool.take().get();
  8. //Compute the result
  9. }
  10. threadPool.shutdown();

通过这段代码,我们可以根据执行结束的顺序获取对应的结果,而无需维护一个 Future 对象的集合。 
这就是本文的全部,通过 Java 为我们提供的各种工具,可以方便的进行多任务的编程,通过使用 Executors、ExecutorService 以及 CompletionService 等工具类,我们可以创建复杂的并行任务执行算法,而且可以轻松改变线程数。

http://825635381.iteye.com/blog/2184605

时间: 2024-10-10 10:29:46

JAVA进阶----主线程等待子线程各种方案比较(转)的相关文章

Java实现主线程等待子线程

本文介绍两种主线程等待子线程的实现方式,以5个子线程来说明: 1.使用Thread的join()方法,join()方法会阻塞主线程继续向下执行. 2.使用Java.util.concurrent中的CountDownLatch,是一个倒数计数器.初始化时先设置一个倒数计数初始值,每调用一次countDown()方法,倒数值减一,他的await()方法会阻塞当前进程,直到倒数至0. join方式代码如下: [java] view plain copy package com.test.thread

设置主线程等待子线程执行的方法

首先要注意的是: 1.java的Main线程结束之后,子线程还在运行.其实主线程已经退出了,但是JVM守护线程会等待所有的线程结束,才会退出.所以我们可以看到,子线程依然在继续执行. 2.那么如何实现主线程等待子线程的执行之后再结束,这个就要用到CountDownLatch,设置要执行的线程的个数,然后再子线程的run方法中调用countDown()的方法,递减线程的计数.在主线程结束之前,调用await()的方法,一直等待. 实现如下: public class Main extends Th

C#主线程等待子线程运行结束

佐左佑右 原文 C#主线程等待子线程运行结束 由于主程序中调用matlab的dll文件进行计算要用较长的时间,主界面会有很长时间的卡顿,造成的用户感受十分不好,因此我想在调用时,将调用放入子线程中,然后在主线程中弹出一个提示框,显示数据正在加载,等子线程运行结束后,主线程继续工作. 使用的是http://hi.baidu.com/oktell/item/5527f51d93abb4a5feded5a8中所提到的方法,用了这篇文章中的第一个方式,即不带参数的. 之后在其中加入了显示和关闭提示框的代

Java并发编程原理与实战六:主线程等待子线程解决方案

本文将研究的是主线程等待所有子线程执行完成之后再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { System.out.println(this.getName() + "子线程开始"); try { // 子线程休眠五秒 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.

Java多线程--让主线程等待子线程执行完毕

使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用countDownLatch.await()方法非常简单的完成主线程的等待: public class ThreadWait { public static void main(String[] args) throws InterruptedException { int threadNumber

Java线程池主线程等待子线程执行完成

今天讨论一个入门级的话题, 不然没东西更新对不起空间和域名~~ 工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线程的流程,  往往需要让主线程指定后, 等待子线程的完成. 这里有几种方式. 站在 主线程的角度, 我们可以分为主动式和被动式. 主动式指主线主动去检测某个标志位, 判断子线程是否已经完成. 被动式指主线程被动的等待子线程的结束, 很明

Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束

Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值.CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行.假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调

Java多线程协作CountDownLatch,主线程等待子线程结束

CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count);构造方法参数指定了计数的次数 public void countDown(); countDown方法,当前线程调用此方法,则计数减一 public void await() awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0 ===============================

Android主线程、子线程通信(Thread+handler)

Android是基于Java的,所以也分主线程,子线程! 主线程:实现业务逻辑.UI绘制更新.各子线程串连,类似于将军: 子线程:完成耗时(联网取数据.SD卡数据加载.后台长时间运行)操作,类似于小兵: 一.子线程向主线程发消息(Thread+handler): 1.主线程中定义Handler: Java代码   Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.h