并发编程-concurrent指南-线程池ExecutorService的使用
有几种不同的方式来将任务委托给 ExecutorService 去执行:
- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(…)
- invokeAll(…)
execute(Runnable)
execute(Runnable) 方法要求一个 java.lang.Runnable 对象,然后对它进行异步执行。以下是使用 ExecutorService 执行一个 Runnable 的示例:
ExecutorService executorService = Executors.newSingleThreadExecutor();  
executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});  
executorService.shutdown(); 
没有办法得知被执行的 Runnable 的执行结果。如果有需要的话你得使用一个 Callable(以下将做介绍)。
submit(Runnable)
submit(Runnable) 方法也要求一个 Runnable 实现类,但它返回一个 Future 对象。这个 Future 对象可以用来检查 Runnable 是否已经执行完毕。
以下是 ExecutorService submit() 示例:
Future future = executorService.submit(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});  
future.get();  //returns null if the task has finished correctly.  
submit(Callable)
submit(Callable) 方法类似于 submit(Runnable) 方法,除了它所要求的参数类型之外。Callable 实例除了它的 call() 方法能够返回一个结果之外和一个 Runnable 很相像。Runnable.run() 不能够返回一个结果。 
Callable 的结果可以通过 submit(Callable) 方法返回的 Future 对象进行获取。以下是一个 ExecutorService Callable 示例:
import java.util.concurrent.*;
public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(new Runnable() {
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(4);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Asynchronous task");
            }
        });
        System.out.println("主方法。。。。");
        try {
            System.out.println(future.get());  //returns null if the task has finished correctly.
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
结果:
主方法。。。。
Asynchronous task
null
future.get()会等待子线程结束后,打印出信息。
submit(Callable)
submit(Callable) 方法类似于 submit(Runnable) 方法,除了它所要求的参数类型之外。Callable 实例除了它的 call() 方法能够返回一个结果之外和一个 Runnable 很相像。Runnable.run() 不能够返回一个结果。 
Callable 的结果可以通过 submit(Callable) 方法返回的 Future 对象进行获取。以下是一个 ExecutorService Callable 示例:
import java.util.concurrent.*;
public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(new Callable(){
            public Object call() throws Exception {
                TimeUnit.SECONDS.sleep(3);
                System.out.println("Asynchronous Callable");
                return "Callable Result";
            }
        });
        System.out.println("主方法。。。。");
        try {
            System.out.println(future.get());  //returns null if the task has finished correctly.
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
结果:
主方法。。。。
Asynchronous Callable
Callable Result
future.get()会等待子线程结束后,打印出信息
invokeAll()
invokeAll() 方法将调用你在集合中传给 ExecutorService 的所有 Callable 对象。invokeAll() 返回一系列的 Future 对象,通过它们你可以获取每个 Callable 的执行结果。
记住,一个任务可能会由于一个异常而结束,因此它可能没有 “成功”。无法通过一个 Future 对象来告知我们是两种结束中的哪一种。
以下是一个代码示例:
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*; public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+",Task 1");
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+",Task 2");
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+",Task 3");
return "Task 3";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+",Task 4");
return "Task 4";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+",Task 5");
return "Task 5";
}
}); try {
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
结果:
pool-1-thread-1,Task 2
pool-1-thread-1,Task 5
pool-1-thread-1,Task 4
pool-1-thread-1,Task 1
pool-1-thread-1,Task 3
future.get = Task 2
future.get = Task 5
future.get = Task 4
future.get = Task 1
future.get = Task 3
ExecutorService 关闭
使用完 ExecutorService 之后你应该将其关闭,以使其中的线程不再运行。
比如,如果你的应用是通过一个 main() 方法启动的,之后 main 方法退出了你的应用,如果你的应用有一个活动的 ExexutorService 它将还会保持运行。ExecutorService 里的活动线程阻止了 JVM 的关闭。
要终止 ExecutorService 里的线程你需要调用 ExecutorService 的 shutdown() 方法。ExecutorService 并不会立即关闭,但它将不再接受新的任务,而且一旦所有线程都完成了当前任务的时候,ExecutorService 将会关闭。在 shutdown() 被调用之前所有提交给 ExecutorService 的任务都被执行。
如果你想要立即关闭 ExecutorService,你可以调用 shutdownNow() 方法。这样会立即尝试停止所有执行中的任务,并忽略掉那些已提交但尚未开始处理的任务。无法担保执行任务的正确执行。可能它们被停止了,也可能已经执行结束。
并发编程-concurrent指南-线程池ExecutorService的使用的更多相关文章
- 并发编程-concurrent指南-线程池ExecutorService的实例
		1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ... 
- Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析
		目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ... 
- Java并发编程:Java线程池
		转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题 ... 
- 【Java并发编程六】线程池
		一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(Blo ... 
- 并发编程-concurrent指南-原子操作类-AtomicInteger
		在java并发编程中,会出现++,--等操作,但是这些不是原子性操作,这在线程安全上面就会出现相应的问题.因此java提供了相应类的原子性操作类. 1.AtomicInteger 
- day33_8_15 并发编程4,线程池与协程,io模型
		一.线程池 线程池是一个处理线程任务的集合,他是可以接受一定量的线程任务,并创建线程,处理该任务,处理结束后不会立刻关闭池子,会继续等待提交的任务,也就是他们的进程/线程号不会改变. 当线程池中的任务 ... 
- 并发编程 --进、线程池、协程、IO模型
		内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ... 
- Java并发编程 (九)  线程调度-线程池
		个人博客网:https://wushaopei.github.io/ (你想要这里多有) 声明:实际上,在开发中并不会普遍的使用Thread,因为它具有一些弊端,对并发性能的影响比较大,如下: ... 
- 并发编程-concurrent指南-计数器CountDownLatch
		java.util.concurrent.CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成. CountDownLatch 以一个给定的数量初始化.count ... 
随机推荐
- XF 进度条和指示器
			<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http:/ ... 
- Socket 专题
			Socket小白篇-附加TCP/UDP简介 Socket 网络通信的要素 TCP和UDP Socket的通信流程图 1.Socket 什么是Socket Socket:又称作是套接字,网络上的两个程序 ... 
- Qt打开外部程序和文件夹需要注意的细节(注意QProcess的空格问题,以及打开本地文件时,需要QUrl::fromLocalFile才可以)
			下午写程序中遇到几个小细节,需要在这里记录一下. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 QProcess *process = new QProcess(this ... 
- Win8Metro(C#)数字图像处理--2.16图像浮雕效果
			原文:Win8Metro(C#)数字图像处理--2.16图像浮雕效果  [函数名称] 图像浮雕效果函数ReliefProcess(WriteableBitmap src) [函数代码] ... 
- HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容。
			解决方法: 找到目录浏览,打开,点击右边的启用就OK了. 
- PostgreSQL在win7上安装详细步骤
			原文:PostgreSQL在win7上安装详细步骤 PostgreSQL安装: 一.windows下安装过程 安装介质:postgresql-9.1.3-1-windows.exe(46M),安装过程 ... 
- win32界面程序开发,自制一个会自动销毁的提示框
			思路:创建线程里面启动窗口,设置定时器关闭该窗口. 创建窗口几个步骤和一般窗口无异,注册.然后createwindow,之后showwinodw,然后消息循环. 在createwindow之后,获取到 ... 
- TThread类详解
			TThread是一个抽象类,可以创建几个独立的线程.类关系 TObject在一个多线程的应用程序中创建一个TThread的后子类代表一个线程.每一新子类的TThread对象的实例是一个新的线程.从TT ... 
- Newtonsoft.Json高级用法之枚举中文转义
			最近看博客园中 焰尾迭的两篇关于"Newtonsoft.Json高级用法"的文章受到了很多人的评论,一度登入到头条推荐. 今天我就不再重复焰尾迭博文中的一些提过的Newtonsof ... 
- VS2013编译Qt5.6.0静态库,并提供了百度云下载(乌合之众)good
			获取qt5.6.0源码包 直接去www.qt.io下载就好了,这里就不详细说了. 这里是我已经编译好的** 链接:http://pan.baidu.com/s/1pLb6wVT 密码: ak7y ** ... 
