线程池ThreadPoolExecutor

来源:互联网 发布:波士顿矩阵分析案例题 编辑:程序博客网 时间:2024/06/06 08:58

 

类: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的大小来实现对派发任务和处理任务的速度的控制,改变这两个值就可以观察不同速率下程序的工作情况。 



原创粉丝点击