类:java.util.concurrent.ThreadPoolExecutor
常用的构造方法:
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> queue, RejectedExecutionHandler handler)
其中:corePoolSize:线程池内维护线程的最少活跃线程数量
maximumPoolSize:线程池内维护线程的最大活跃线程数量
keepAliveTime:线程池维护线程所允许的最大空闲(不干活)时间
unit:线程池维护线程所允许的空闲时间的单位 ;可选的参数是java.util.concurrent.TimerUnit的几个静态属性:NANOSECONDS(纳秒)、MICROSECONDS(微秒)、MILLISECONDS(毫秒)、SECONDS(秒)
queue:线程池所使用的缓冲队列。常用的有java.util.concurrent.ArrayBlockingQueue……handler:线程池对被拒绝的任务的执行的处理策略。其中handler有四种策略,分别是:
1、ThreadPoolExecutor.AbortPolicy(),跑出java.util.concurrent.RejectedExecutionException异常。
2、ThreadPoolExecutor.CallerRunsPolicy(),重试添加当前的任务,他会自动重复调用execute()方法。
3、ThreadPoolExecutor.DiscardOldestPolicy() ,抛弃旧的任务。
4、ThreadPoolExecutor.DiscardPolicy(),抛弃当前任务。
PS:
首先给大家展示的是我们的线程池要执行的任务
/** * 线程池执行的任务 */ public class ThreadPoolTask implements Runnable, Serializable { private static final long serialVersionUID = 0; private Object threadPoolTaskData; // 保存任务所需要的数据 public ThreadPoolTask(Object tasks) { this.threadPoolTaskData = tasks; } public void run() { // 处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句 System.out.println(Thread.currentThread().getName()+"============================start .." + threadPoolTaskData); try{ Thread.sleep(2000);//设置一段延时,便于观察 } catch (Exception e){ e.printStackTrace(); } threadPoolTaskData = null; } public Object getTask() { return this.threadPoolTaskData; } }
线程池:
public class MyThread { public static void main(String[] args) { // 构造一个线程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 5, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),//其中这里的3,表示的是队列深度为4 new ThreadPoolExecutor.AbortPolicy() //new ThreadPoolExecutor.CallerRunsPolicy() //new ThreadPoolExecutor.DiscardOldestPolicy() //new ThreadPoolExecutor.DiscardPolicy() ); for (int i = 1; i <= 10; i++){ try{ String task = "task@ " + i;// 产生一个任务,并将其加入到线程池 System.out.println("put " + task); threadPool.execute(new ThreadPoolTask(task)); Thread.sleep(2);// 便于观察,等待一段时间 } catch (Exception e){ e.printStackTrace(); } } } }
ThreadPoolExecutor.AbortPolicy(),跑出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy(),重试添加当前的任务,他会自动重复调用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy(),抛弃旧的任务。
ThreadPoolExecutor.DiscardPolicy(),抛弃当前任务。
结论:
一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。一般任务除了处理方式外,还需要处理的数据,处理的数据通过构造方法传给任务。当一个任务通过execute(Runnable)方法欲添加到线程池时:
1、如果此时线程池中的数量小于corePoolSize(线程池最小活跃线程数量),即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2、如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 queue还未满,那么任务被放入缓冲队列。
3、如果此时线程池中的数量大于corePoolSize,缓冲队列queue已经满了,并且线程池中的数量小于maximumPoolSize(线程池最大活跃线程数量),建新的线程来处理被添加的任务。
4、如果此时线程池中的数量大于corePoolSize,缓冲队列queue已经满了,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。5、当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime(线程池维护线程所允许的最大空闲(不干活)时间),线程将被终止。这样,线程池可以动态的调整池中的线程数。
6、通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制,改变这两个值就可以观察不同速率下程序的工作情况。
线程池ThreadPoolExecutor
最新推荐文章于 2024-04-22 20:30:36 发布