java多线程:ExecutorService解析(五)
来源:互联网 发布:常见web前后端数据交互 编辑:程序博客网 时间:2024/05/16 00:35
前面几篇博客写到的多线程实现基本都是显式调用了Thread的start()方法,除了这种方法有没有其他的实现方法呢,这里我们来看下java.util.concurrent包下的ExecutorService实现。
看一个简单的例子:
public class ThreadTest {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}});executorService.shutdown();}}
这个例子其实很容易看懂,首先使用newFixedThreadPool() 工厂方法创建一个 ExecutorService ,上述代码创建了一个可以容纳10个线程任务的线程池。然后向execute() 方法中传递一个异步的 Runnable 接口的实现,这样做会让 ExecutorService 中的某个线程执行这个 Runnable线程。
由此可以看出ExecutorService使用线程池来管理线程,可以重复利用已经创建出来的线程而不是每次都必须新创建线程,节省了一部分的开销。线程池可以很方便的管理线程的大小和当前在执行的线程数量。
除了上述的newFixedThreadPool实现方式, ExecutorService 实例的创建方式有以下几种:ExecutorService executorService1 = Executors.newSingleThreadExecutor();ExecutorService executorService2 = Executors.newFixedThreadPool(10);ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
说完了创建我们再看ExecutorService中的方法:
package java.util.concurrent;import java.util.List;import java.util.Collection;public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
这里有几种不同的方式让你将任务委托给一个ExecutorService:
1 execute(Runnable)
2 submit(Runnable)
3 submit(Callable)
4 invokeAny(...)
5 invokeAll(...)
execute(Runnable)
方法 execute(Runnable)接收一个 java.lang.Runnable 对象作为参数,并且以异步的方式执行它。如下是一个使用 ExecutorService 执行 Runnable的例子:
ExecutorService executorService =Executors.newSingleThreadExecutor(); executorService.execute(newRunnable() { public void run() { System.out.println("Asynchronous task"); } }); executorService.shutdown();
使用这种方式没有办法获取执行 Runnable之后的结果,如果你希望获取运行之后的返回值,就必须使用 接收 Callable 参数的 execute() 方法,后者将会在下文中提到。
submit(Runnable)
方法 submit(Runnable)同样接收一个 Runnable 的实现作为参数,但是会返回一个 Future 对象。这个 Future 对象可以用于判断 Runnable是否结束执行。如下是一个 ExecutorService 的 submit() 方法的例子:
Future future = executorService.submit(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); //如果任务结束执行则返回 null System.out.println("future.get()=" + future.get());
submit(Callable)
方法 submit(Callable) 和方法submit(Runnable) 比较类似,但是区别则在于它们接收不同的参数类型。Callable 的实例与 Runnable 的实例很类似,但是Callable 的 call() 方法可以返回一个结果。方法 Runnable.run() 则不能返回结果。
Callable 的返回值可以从方法submit(Callable) 返回的 Future 对象中获取。如下是一个 ExecutorService Callable 的样例:
Future future = executorService.submit(newCallable(){ public Object call() throwsException { System.out.println("AsynchronousCallable"); return "CallableResult"; } }); System.out.println("future.get()= " + future.get());
上述样例代码会输出如下结果:
Asynchronous Callablefuture.get() = Callable Result
inVokeAny()
方法 invokeAny() 接收一个包含Callable 对象的集合作为参数。调用该方法不会返回 Future 对象,而是返回集合中某一个 Callable对象的结果,而且无法保证调用之后返回的结果是哪一个 Callable,只知道它是这些 Callable 中一个执行结束的 Callable 对象。
如果一个任务运行完毕或者抛出异常,方法会取消其它的Callable 的执行。
以下是一个样例:
Future future = executorService.submit(newCallable(){ public Object call() throwsException { System.out.println("AsynchronousCallable"); return "CallableResult"; } }); System.out.println("future.get()= " + future.get()); ExecutorService executorService =Executors.newSingleThreadExecutor(); Set<Callable<String>>callables = new HashSet<Callable<String>>(); callables.add(newCallable<String>() { public String call() throwsException { return "Task1"; } }); callables.add(newCallable<String>() { public String call() throwsException { return "Task2"; } }); callables.add(newCallable<String>() { public String call() throwsException { return "Task3"; } }); String result =executorService.invokeAny(callables); System.out.println("result =" + result); executorService.shutdown();
以上样例代码会打印出在给定的集合中的某一个Callable 的返回结果。我尝试运行了几次,结果都在改变。有时候返回结果是”Task 1”,有时候是”Task 2”,等等。
invokeAll()
方法 invokeAll()会调用存在于参数集合中的所有 Callable 对象,并且返回一个包含 Future 对象的集合,你可以通过这个返回的集合来管理每个 Callable的执行结果。
需要注意的是,任务有可能因为异常而导致运行结束,所以它可能并不是真的成功运行了。但是我们没有办法通过Future 对象来了解到这个差异。
以下是一个代码样例:
ExecutorService executorService =Executors.newSingleThreadExecutor(); Set<Callable<String>>callables = new HashSet<Callable<String>>(); callables.add(newCallable<String>() { public String call() throwsException { return "Task1"; } }); callables.add(newCallable<String>() { public String call() throwsException { return "Task2"; } }); callables.add(newCallable<String>() { public String call() throwsException { return "Task3"; } }); List<Future<String>>futures = executorService.invokeAll(callables); for(Future<String> future :futures){ System.out.println("future.get = " +future.get()); } executorService.shutdown();
ExecuteService 服务的关闭
当使用 ExecutorService完毕之后,我们应该关闭它,这样才能保证线程不会继续保持运行状态。
举例来说,如果你的程序通过 main()方法启动,并且主线程退出了你的程序,如果你还有一个活动的 ExecutorService 存在于你的程序中,那么程序将会继续保持运行状态。存在于ExecutorService 中的活动线程会阻止Java虚拟机关闭。
为了关闭在 ExecutorService中的线程,你需要调用 shutdown() 方法。ExecutorService并不会马上关闭,而是不再接收新的任务,壹但所有的线程结束执行当前任务,ExecutorServie 才会真的关闭。所有在调用 shutdown()方法之前提交到 ExecutorService 的任务都会执行。
如果你希望立即关闭ExecutorService,你可以调用 shutdownNow()方法。这个方法会尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。但是对于正在执行的任务,是否能够成功关闭它是无法保证的,有可能他们真的被关闭掉了,也有可能它会壹直执行到任务结束。这是一个最好的尝试。
- java多线程:ExecutorService解析(五)
- java多线程:ExecutorService多线程实例(六)
- Java Executor并发框架(五)ExecutorService
- Java ExecutorService 多线程实践(一)
- java多线程[9]:线程池(ExecutorService)
- Java多线程之ExecutorService
- ExecutorService实现java多线程
- Java多线程之ExecutorService
- Java多线程之ExecutorService
- JAVA多线程计算ExecutorService
- JAVA多线程之ExecutorService
- java多线程之ExecutorService
- Java多线程系列-ExecutorService
- JAVA多线程之Executor&ExecutorService
- java 使用ExecutorService 建立多线程
- Java多线程--ExecutorService的使用
- Java多线程工具包java.util.concurrent---ExecutorService
- ExecutorService多线程
- 栈空间和堆空间
- 机器学习算法之线性回归(Linear Regression)
- 分布式系列 单点登录和session共享实现
- Rundll32.exe参数传递问题解决方法
- 简单MD5加密类
- java多线程:ExecutorService解析(五)
- BZOJ1050(HAOI2006)[旅行comf]--并查集
- Frank的【python网络爬虫系列教程】~序章&目录
- JAVA数据流概念及标准数据流的实现
- 暑假来临!花了点时间用flash3d做了一个MV歌曲!
- httpResult
- 源码安装 mysql的种种问题(已解决)
- python使用lxml解析html获取页面内所有叶子节点的xpath路径
- Rundll32