#java线程池:ThreadPoolExecutor
-
自定义线程池,按照不同策略创建ThreadPoolExecutor类对象
它的构造方法如下
public ThreadPoolExecutor(int corePoolSize,//核心线程池大小,初始化时创建多少线程 int maximumPoolSize,//线程池最多有多少线程 long keepAliveTime,//空闲线程存活时间 TimeUnit unit,//存活时间的时间单位(天,小时,分,秒...) BlockingQueue<Runnable> workQueue,//任务队列,可以是无界队列或者有界队列 ThreadFactory threadFactory,//新建线程工厂 RejectedExecutionHandler handler) {....}//任务拒绝策略
- 当传入的是有界队列(如LinkedBlockingQueue(int n))时,当有任务来传递来时
- 如果当前存活线程小于corePoolSize则创建线程处理
- 如果等于corePoolSize时
- 当无界队列不满时将任务放入有界队列,当有线程空闲时从无界队列中取出任务执行
- 当无界队列已满时将拒绝任务,如何拒绝,取决于上面的拒绝策略,默认抛出异常
- 当传入的是无界队列(如LinkedBlockingQueue()) 时,当有任务传递来时
- 当存活线程小于corePoolSize时,创建线程处理
- 否则放入无界队列中,直至系统资源耗尽.
- maximumPoolSize参数失去意义
- 当传入的是有界队列(如LinkedBlockingQueue(int n))时,当有任务来传递来时
-
JDK拒绝策略
- AbortPolicy 直接抛出异样
- CallerRunsPolicy 只要线程池未关闭,直接在调用者线程中运行当前被丢弃的任务
- DiscardOldestPolicy 丢弃最老的一个请求,再尝试提交当前任务
- DiscardPolicy 丢弃无法处理的任务,不给任何处理
- 自定义拒绝策略,实现RejectedExecutionHandlie接口
-
常见的自定义策略,写入日志后丢弃请求.
public class MyRejected implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // TODO Auto-generated method stub System.out.println("执行拒绝策略"); }
-
}
-
线程池关闭
- shutdownNow()会停止当前正在执行的任务,清除已提交但是尚未运行的任务,然后终止线程池。
- shutdown()会等待已经提交的所有任务执行完毕才终止线程池。
-
例子
-
有界队列
package ThreadPool; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolTest { public static void main(String[] args) { ThreadPoolExecutor pool =new ThreadPoolExecutor(2,3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(2));//队列长度为2 ThreadTast tast1=new ThreadTast(1); ThreadTast tast2=new ThreadTast(2); ThreadTast tast3=new ThreadTast(3); ThreadTast tast4=new ThreadTast(4); ThreadTast tast5=new ThreadTast(5); ThreadTast tast6=new ThreadTast(6); pool.execute(tast1);//直接执行 pool.execute(tast2);//直接执行 pool.execute(tast3);//线程都在运行,则加入队列 pool.execute(tast4);//线程都在运行,加入队列 pool.execute(tast5);//当前活动线程小于最大线程,则创建线程执行 pool.execute(tast6);//抛出异常 pool.shutdown(); } } class ThreadTast extends Thread{ private int i; public ThreadTast(int i){ this.i=i; } public void run() { // TODO Auto-generated method stub super.run(); System.out.println("tast"+i+"正在执行"); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
-
-
JDK中常见的线程池
-
FixedThreadPool,使用的是无界队列,线程空闲存活时间为0,corePoolSize和maximumPoolSize大小一样
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
-
CachedThreadPool,根据需要创建线程,使用的SynchronousQueue(),是没有线程数量限制,来一个任务,如没有空闲线程及创建线程处理,极端情况下会耗尽cpu和内存,可以设置空闲线程存活时间
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
-
ScheduledThreadPool,使用DelayedQueue当做队列,用于执行定时任务.
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue()); }
-
SingleThreadExecutor,线程数量为1的线程池
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
-