Executor与ThreadPoolExecutor
来源:互联网 发布:PHP地址匹配正则 编辑:程序博客网 时间:2024/06/03 23:42
创建线程池
- 创建无界线程池
ExecutorService executor = Executors.newCachedThreadPool();
- 创建固定数量的线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
- 创建单一线程的线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
- 创建定时或周期任务的线程池
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
使用Executors创建线程池
一般使用Executors的静态方法创建线程池,需要定制化可以使用ThreadPoolExecutor类进行详细参数设定。
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); for(int i=0;i<5;i++){ final int k = i; executorService.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+" user"+(k+1)); } }); } Thread.sleep(3000); for(int i=0;i<5;i++){ final int k = i; executorService.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+" user"+(k+1)); } }); } }}
可以观察到使用newCachedThreadPool创建的线程池里面的线程得到了复用,因为线程池线程名称唯一(从源码可以看出默认新创建的线程会保持60秒)
使用Executors的静态方法底层是调用了ThreadPoolExecutor类
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
使用newCachedThreadPool(ThreadFactory) 替换默认线程工厂
public class MyThreadFactory implements ThreadFactory{ @Override public Thread newThread(Runnable r) { Random random = new Random(); Thread thread = new Thread(r); thread.setName("yuchuan-thread-" + random.nextInt(100)); return thread; }}public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyThreadFactory myThreadFactory = new MyThreadFactory(); ExecutorService executorService = Executors.newCachedThreadPool(myThreadFactory); executorService.execute(new Runnable() { @Override public void run() { System.out.println("running " + Thread.currentThread().getName()); } }); }}
ThreadPoolExecutor 使用Executors的静态方法底层都是调用了ThreadPoolExecutor类
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
线程池核心数量与任务数关系
如果线程数量 < corePoolSize 则直接执行任务,不放入扩展队列Queue中。
ThreadPoolExecutor executor = new ThreadPoolExecutor(7,8,5,TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>())
如果corePoolSize < 线程数量 < maximumPoolSize且队列使用LinkedBlockingDeque,则放入队列;如果队列使用SynchronousQueue类,会立即执行,且当时间keepAliveTime超过5秒时,清除空闲线程。
BlockingQueue 常用的实现类LinkedBlockingQueue 和ArrayBlockingQueue。用 LinkedBlockingQueue的好处在于没有大小限制,所以执行execute()不会抛出异常。线程池中运行的线程数也永远不会超过corePoolSize,因为其他多于的线程被放入LinkedBlockingQueue队列,keepAliveTime参数也就没有意义。
如果线程数量 > maximumPoolSize 且队列使用 LinkedBlockingQueue 则会放入队列;若队列使用 SynchronousQueue 则会抛出拒绝异常
shutdown() VS shutdownNow()
方法shutdown()的作用是使当前未执行完的线程继续执行,而不再添加新的任务task,还有shutdown()方法不会阻塞,调用shutdown()方法后,主线程main就马上结束了,而线程池会继续运行直到所有任务执行完才会停止。如果不调用shutdown()方法,那么线程池会一直保持下去,以便随时执行被添加的task任务。
方法shutdownNow()的作用是中断所有的任务task,并且抛出InterruptedException异常,前提是在Runnable中使用if(Thread.currentThread.isInterrupted()==true)语句来判断当前线程的中断状态,而未执行的线程不再执行,也就是从执行队列中清除。如果没有if(Thread.currentThread.isInterrupted()==true)语句及抛出异常的代码,则池中正在运行的线程直到执行完毕,而未执行的线程将不再执行,也从执行队列中清除。
public class MyRunnable1 implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()+" " + System.currentTimeMillis()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" end"); }}public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable1 myRunnable1 = new MyRunnable1(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); pool.execute(myRunnable1); pool.execute(myRunnable1); pool.execute(myRunnable1); pool.execute(myRunnable1); Thread.sleep(1000); pool.shutdown(); pool.execute(myRunnable1); System.out.println("main end!"); }}
结果线程池执行shutdown()关闭之后,状态变为SHUTDOWN状态。此时如果再添加任务会抛出RejectedExecutionException异常,但线程池中的任务不会立刻退出,直到任务处理完成,线程池退出。说明 shutdown 关闭线程池之后,线程(正在执行或是在队列中)还会正常执行
shutdownNow()方法是使线程池的状态变为STOP状态,并试图停止所有正在执行的线程(如果有if判断则认为的抛出异常),不在处理还在队列中等待的任务,可以通过List list = pool.shutdownNow()返回那些未执行的任务。
public class MyRunnable1 implements Runnable { @Override public void run() { try{ for(int i=0;i<Integer.MAX_VALUE/50;i++){ Math.random(); Math.random(); Math.random(); Math.random(); // 被中断线程时候抛出异常并执行异常操作 if(Thread.currentThread().isInterrupted()==true){ System.out.println("is interrupted!"); throw new InterruptedException(); } } System.out.println("complete!"); }catch (InterruptedException e){ System.out.println("catch interrupted!"); e.printStackTrace(); } }}public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable1 myRunnable1 = new MyRunnable1(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); pool.execute(myRunnable1); pool.execute(myRunnable1); pool.execute(myRunnable1); pool.execute(myRunnable1); Thread.sleep(1000); // 执行shutdownNow()可以返回List<Runnable>,存储的是未运行的任务 List<Runnable> list = pool.shutdownNow(); System.out.println("main end! " + list.size()); }}
使用isShutdown()判断线程池是否关闭,判断这个命令发出或未发出。
pool.isTerminating()和pool.isTerminated()判断线程池正在停止还是已停止状态
如果线程池关闭后,也就是所有任务都已完成,则方法isTerminated()返回true
awaitTermination(long timeout, TimeUnit unit)作用就是查看在制定的时间之间,线程池是否已经终止工作,也就是最多等待多少时间去判断线程是否已经终止工作,此方法需要shutdown()方法的配合
public class MyRunnable1 implements Runnable { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }}public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable1 myRunnable = new MyRunnable1(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.shutdown(); System.out.println("main begin"); System.out.println(pool.awaitTermination(1, TimeUnit.SECONDS)); System.out.println(pool.awaitTermination(1, TimeUnit.SECONDS)); System.out.println(pool.awaitTermination(1, TimeUnit.SECONDS)); System.out.println(pool.awaitTermination(1, TimeUnit.SECONDS)); System.out.println(pool.awaitTermination(1, TimeUnit.SECONDS)); System.out.println("main end"); }}结果 main beginfalsefalsefalsetruetruemain end
方法awaitTermination()与shutdown()结合可以实现等待执行完毕的效果。原理就是应用awaitTermination()方法具有阻塞性,如果awaitTermination()方法正在阻塞的过程中任务执行完毕,则awaitTerminal()取消阻塞继续执行后面的代码,如下所示。
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { System.out.println("begin"); MyRunnable1 myRunnable = new MyRunnable1(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.shutdown(); System.out.println(pool.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS)); System.out.println("main end"); }}
ThreadFactory+execute()+UncaughtExceptionHandler处理异常
ThreadPoolExecutor通过设置ThreadFactory,实现UncaughtExceptionHandler来处理异常
public class MyRunnable1 implements Runnable { @Override public void run() { int a = 5/0; }}public class MyThreadFactoryB implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("my name "); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("自定义处理异常 " +t.getName()+" " + e.getMessage()); e.printStackTrace(); } }); return thread; }}public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable1 myRunnable = new MyRunnable1(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); pool.setThreadFactory(new MyThreadFactoryB()); pool.execute(myRunnable); }}
set/getRejectedExcutionHandler()
实现RejectedExecutionHandler接口来处理任务被拒绝执行时的行为。
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable1 one = new MyRunnable1("one"); MyRunnable1 two = new MyRunnable1("two"); MyRunnable1 three = new MyRunnable1("three"); MyRunnable1 four = new MyRunnable1("four"); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 10, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); // 匿名函数处理拒绝执行行为 pool.setRejectedExecutionHandler(new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println(((MyRunnable1)r).getUsername()+" is rejected!"); } }); pool.execute(one); pool.execute(two); pool.execute(three); pool.execute(four); }}结果four is rejected!pool-1-thread-1 begin 1480148850840pool-1-thread-2 begin 1480148850840pool-1-thread-3 begin 1480148850840pool-1-thread-2 end 1480148853845pool-1-thread-3 end 1480148853845pool-1-thread-1 end 1480148853845
allowsCoreThreadTimeOut()(boolean) 配置核心线程是否超时,超时则和其他线程一样清除
getCompletedTaskCount()
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " print "); } catch (InterruptedException e) { e.printStackTrace(); } } }; ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); pool.execute(runnable); pool.execute(runnable); pool.execute(runnable); pool.execute(runnable); pool.execute(runnable); Thread.sleep(1000); System.out.println(pool.getCompletedTaskCount()); Thread.sleep(1000); System.out.println(pool.getCompletedTaskCount()); Thread.sleep(1000); System.out.println(pool.getCompletedTaskCount()); Thread.sleep(1000); System.out.println(pool.getCompletedTaskCount()); }}
线程池ThreadPoolExecutor的拒绝策略
线程池中的资源全部被占用的时候,读新添加的Task任务有不同的处理策略,在默认情况下,有四种处理方式:
1. AbortPolicy:当任务添加到线程池被拒绝时,抛出RejectExecutionException异常
2. CallerRunsPolicy:使用调用线程池的Thread线程对象处理被拒绝的任务
3. DiscardOldestPolicy:线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中
4. DiscardPolicy:线程池将丢弃被拒绝的任务
- AbortPolicy
ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.AbortPolicy());
- CallerRunsPolicy
由调用者处理被拒绝的任务
MyRunnable2 myRunnable = new MyRunnable2(); LinkedBlockingDeque<Runnable> queue = new LinkedBlockingDeque<>(2); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy()); System.out.println("a begin "); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); pool.execute(myRunnable); System.out.println("a end"); pool.shutdown(); pool.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);结果a begin end mainend pool-1-thread-3end pool-1-thread-1end pool-1-thread-2end maina endend pool-1-thread-3end pool-1-thread-1
- DiscardOldestPolicy
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { ArrayBlockingQueue queue = new ArrayBlockingQueue(2); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.DiscardOldestPolicy()); for(int i=0;i<5;i++){ MyRunnable myRunnable = new MyRunnable("Runnable"+(i+1)); pool.execute(myRunnable); } Thread.sleep(500); Iterator iterator = queue.iterator(); while(iterator.hasNext()){ MyRunnable mr = (MyRunnable) iterator.next(); System.out.println(mr.getUsername()); } pool.execute(new MyRunnable("Runnable6")); pool.execute(new MyRunnable("Runnable7")); iterator = queue.iterator(); while(iterator.hasNext()){ MyRunnable mr2 = (MyRunnable) iterator.next(); System.out.println(mr2.getUsername()); } pool.shutdown(); pool.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); }结果Runnable1 runRunnable5 runRunnable2 runRunnable3Runnable4Runnable6Runnable7Runnable6 runRunnable7 run}
- DiscardPolicy
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { MyRunnable2 myrunnable = new MyRunnable2(); ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2); ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.DiscardPolicy()); executor.execute(myrunnable); executor.execute(myrunnable); executor.execute(myrunnable); executor.execute(myrunnable); executor.execute(myrunnable); executor.execute(myrunnable); executor.execute(myrunnable); Thread.sleep(1000); executor.shutdown(); executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); }}结果end pool-1-thread-1end pool-1-thread-3end pool-1-thread-2end pool-1-thread-1end pool-1-thread-3
afterExecute()和beforeExecute()
重写这两个方法可以对线程池中执行的线程对象实施监控。
public class MyThreadPoolExecutor extends ThreadPoolExecutor { public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); System.out.println(((MyRunnable)r).getUsername()+" execute finish!"); } @Override protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); System.out.println(((MyRunnable)r).getUsername()+" prepare to execute!"); }}public static void main(String[] args) throws InterruptedException { MyThreadPoolExecutor executor = new MyThreadPoolExecutor(2, 2, Integer.MAX_VALUE, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); executor.execute(new MyRunnable("thread1")); executor.execute(new MyRunnable("thread2")); executor.execute(new MyRunnable("thread3")); executor.execute(new MyRunnable("thread4")); }
ExecutorService可以使用remove方法移除未被执行的任务,前提是任务是使用execute()方式提交的;如果使用submit提交的任务,未被执行也不能删除此任务。
ExecutorService中submit和execute的区别
* 接受的参数不一样
ExecutorService中的方法
1) Future<?> submit(Runnable task);2) <T> Future<T> submit(Runnable task, T result);3) <T> Future<T> submit(Callable<T> task);
Executor 接口唯一方法
void execute(Runnable command);
- submit有返回值,而execute没有
- submit方便Exception处理
submit可以直接捕获异常,通过catch ExecutionException的方式
public class RunTest { public static void main(String[] args){ ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); Future future = executor.submit(new Callable<String>() { @Override public String call() throws Exception { Integer.parseInt("a"); return "我是返回值"; } }); try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { System.out.println("捕获到异常"); e.printStackTrace(); } }}
execute捕获异常需要通过自定义ThreadFactory的方式进行捕获
public class RunTest { public static void main(String[] args){ ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); executor.setThreadFactory(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("execute()使用自定义方法捕获异常"); e.printStackTrace(); } }); return t; } }); executor.execute(new Runnable() { @Override public void run() { Integer.parseInt("a"); } }); }}
Test
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(2); // execute方式 pool.execute(new RunnableTest("Task1")); // submit方式 Future<?> future = pool.submit(new RunnableTest("Task2")); try{ if(future.get()==null){ System.out.println("任务完成"); } } catch (ExecutionException e) { System.out.println(e.getCause().getMessage()); e.printStackTrace(); } } static class RunnableTest implements Runnable{ private String taskName; public RunnableTest(String taskName){ this.taskName = taskName; } @Override public void run() { System.out.println("inside "+taskName); throw new RuntimeException("Runtime Exception from inside " + taskName); } }}
get方法测试
getActiveCount()正在执行任务的线程
getPoolSize() 线程池中总共的线程
getCompletedTaskCount() 已经任务执行完毕的线程
public class ExecutorTest { public static void main(String[] args) throws InterruptedException { try{ MyRunnable2 myrunnable = new MyRunnable2(); SynchronousQueue<Runnable> queue = new SynchronousQueue<>(); ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 5, 5, TimeUnit.SECONDS, queue); pool.execute(myrunnable); pool.execute(myrunnable); pool.execute(myrunnable); System.out.println(pool.getActiveCount()+" " + pool.getPoolSize()); Thread.sleep(7000); System.out.println(pool.getActiveCount()+" " + pool.getPoolSize()); }catch (InterruptedException e){ e.printStackTrace(); } }}
自定义拒绝策略
接口RejectedExecutionHandler的主要作用是当线程池关闭后依然有任务要执行时,可以实现一些处理
public class RunTest { public static void main(String[] args){ ExecutorService service = Executors.newCachedThreadPool(); ThreadPoolExecutor executor = (ThreadPoolExecutor)service; executor.setRejectedExecutionHandler(new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println(((FutureTask)r).toString()+" is rejected!"); } }); service.submit(new MyRunnable("A")); service.submit(new MyRunnable("B")); service.submit(new MyRunnable("C")); executor.shutdown(); service.submit(new MyRunnable("D")); }}
- Executor与ThreadPoolExecutor
- Executor-ThreadPoolExecutor实现
- Executor实现类--ThreadPoolExecutor
- java中Executor、ExecutorService、ThreadPoolExecutor
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- Android 线程池框架、Executor、ThreadPoolExecutor详解
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- Java中Executor、ExecutorService、ThreadPoolExecutor介绍
- SUM(CASE WHEN RECHARGE_STATUS =1 THEN 1 ELSE 0 END) as 成功数量,
- HM/JEM检查当前CU的模式是否是最优模式
- Glide 中高斯模糊效果,与减小Apk时的小冲突
- js 事件
- 分布式事务简谈
- Executor与ThreadPoolExecutor
- 20161129-部门会议(分工协作)
- 天马行空
- 笔记:Maven
- Hadoop伪分布式模式安装配置步骤
- 在eclipse中使用Tomcat8.0时出现Could not publish server ...错误
- UVA 1331 Minimax Triangulation
- salt源码安装软件和yum安装软件
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(下)