Java并发之Executor
来源:互联网 发布:董洁出轨 知乎 编辑:程序博客网 时间:2024/06/09 10:36
Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的Java多线程程序,本文讲的是Executor框架。
Executor结构如下:
1、Runnable与Callable
(1)Callable规定的方法是call(),Runnable规定的方法是run()。
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。 它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。 通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
Runnable task = new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("run method " + LocalDateTime.now() + "" + Thread.currentThread()); } }; Callable<String> call = new Callable<String>() { @Override public String call() throws Exception { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return ("call method " + LocalDateTime.now() + "" + Thread.currentThread()); } };
2、创建线程池
Executors 类提供了一系列工厂方法用于创线程池,返回的线程池都实现了ExecutorService接口
(1)newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
(2)newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
(3)newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
(4)newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
3、ExecutorService 线程池方法
void shutdown();
状态则立刻变成SHUTDOWN状态,以后不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出
sList<Runnable> shutdownNow();
调用Thread.interrupt来实现线程的立即退出
boolean isShutdown();
是否executor已经shutdown
boolean isTerminated();
是否所有的线程都已经运行完成
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
直到所有任务都完成后,关闭执行请求,或超时发生,或当前线程是中断,以先发生者为准。
<T> Future<T> submit(Callable<T> task);
提交一个任务用于执行,返回Future< T>。
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果。
下面看具体代码:
public class ExecutorDemo1 { ExecutorService executor = Executors.newFixedThreadPool(10); ExecutorService executorService = Executors.newCachedThreadPool(); Runnable task = new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("run method " + LocalDateTime.now() + "" + Thread.currentThread()); } }; Callable<String> call = new Callable<String>() { @Override public String call() throws Exception { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return ("call method " + LocalDateTime.now() + "" + Thread.currentThread()); } }; @Test //Runnable public void method1() throws Exception { for (int i = 0; i < 100; i++) { executor.execute(task); } executor.shutdown(); executor.awaitTermination(100, TimeUnit.SECONDS); } @Test //Callable public void method2() throws Exception { List<Future<String>> list = new ArrayList<>(); //1、循环的搭配Future,再添加到List<Future<String>>中 for (int i = 0; i < 100; i++) { Future<String> submit = executor.submit(call); list.add(submit);// System.out.println(submit.get()); //为什么需要得到List<Future<String>> 再循环,不直接打印呢 } //2、直接的得到List<Callable<String>>,用invokeAll方法得到返回至// List<Callable<String>> listCall = new ArrayList<>();// for (int i = 0; i < 100; i++) {// listCall.add(call);// }// list = executor.invokeAll(listCall); //1 2 for (Future<String> future : list) { System.out.println(future.get()); } executor.shutdown(); executor.awaitTermination(15, TimeUnit.SECONDS); } @Test callable 抓取异常 public void method4() throws Exception { List<Future<String>> list = new ArrayList<>(); for (int i = 0; i < 100; i++) { Future<String> submit = executor.submit(new CallableTest(i)); list.add(submit); } for (Future<String> future : list) { try { System.out.println(future.get()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (ExecutionException e1) { e1.printStackTrace(); } } executor.shutdown(); executor.awaitTermination(15, TimeUnit.SECONDS); }}//自己抛出异常,自己抓取异常class CallableTest implements Callable<String> { int i; CallableTest(int i) { this.i = i; } @Override public String call() throws Exception { if (i == 50) { throw new InterruptedException("我故意抛出的异常"); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return ("call method " + LocalDateTime.now() + "" + Thread.currentThread()); }}
4、CompletionService
当用Callable接口来实现具有返回值的线程时,使用线程池的submit方法提交Callable任务,利用submit方法返回的Future,调用此存根的get方法来获取整个线程池中所有任务的运行结果。需要用Collection保存所有的Future,然后在主线程中遍历这个Collection并调用 .get() 方法取得线程的返回值。这个时候主线程不能保证首先获得的是最先完成的线程返回值,它只是按加入线程池的顺序返回。因为 .get 方法是阻塞方法,后面的任务完成了,前面的任务却没有完成,主程序就那样等待在那儿,只到前面的完成了,它才知道原来后面的也完成了。
用CompletionService类,它整合了Executor和BlockingQueue(阻塞队列)的功能。你可以将Callable任务提交给它去执行,然后使用类似于队列中的take方法获取线程的返回值。使用CompletionService来维护处理线程不的返回结果时,主线程总是能够拿到最先完成的任务的返回值,而不管它们加入线程池的顺序。
继续接上面的代码:
@Test //CompletionService public void method3() throws Exception { CompletionService<String> completionService = new ExecutorCompletionService<String>(executor); for (int i = 0; i < 100; i++) { completionService.submit(call); } for(int i = 0; i < 100; i++) { String string = completionService.take().get(); System.out.println(string); } executor.shutdown(); executor.awaitTermination(15, TimeUnit.SECONDS); }
- 【Java】并发之Executor
- Java并发之Executor
- Java并发之Executor框架
- [沧海拾遗]java并发之Executor
- Java并发编程-Executor框架之ScheduledThreadPoolExecutor
- Java并发编程-Executor框架之CompletionService
- Java并发框架Executor
- java并发--Executor 框架
- Java并发框架Executor
- Java并发系列 - Java Concurrency Utilities 之 Executor 框架
- Java并发编程之线程管理(Executor框架11)
- Java并发编程之线程管理(Executor框架12)
- Java并发编程之线程管理(Executor框架13)
- Java并发编程之线程管理(Executor框架14)
- Java并发编程之线程管理(Executor框架15)
- Java并发编程之线程管理(Executor框架16)
- Java并发编程系列之十五:Executor框架
- Java并发编程-Executor框架之Callable和Future接口
- 【第七周 项目1-建立顺序环形队列算法库】
- HDU 5391 Zball in Tina Town(威尔逊定理)
- Unity Animation
- Java 基本数据类型
- 大数据之hadoop[MapReduce]学习 笔记
- Java并发之Executor
- 单例模式
- 十进制转换为十六进制
- java--通配符类型
- 栈的应用 之 用算符优先法求表达式的值
- Java 变量类型
- php原理
- struts2入门
- ORACLE触发器详解