ThreadPoolExecutor的扩展

    在java中,在并发的情况可以使用ThreadPoolExecutor,但为了提高吞吐量和性能,可以扩展ThreadPoolExecutor。

    ThreadPoolExecutor的执行流程:

  • 当core线程数大于当前任务数时,可以创建新的线程;
  • 当core线程数小于当前执行的任务数时,则将任务加入到队列;
  • 当队列已满时,则开始创建新的线程,当线程数达到max线程数时,则会抛出RejectedExcutionException异常。

    这样也行会出现一个问题,如果当任务数不断增大,core线程数已不足于应付时,就会频繁的将任务加入队列,不断的创建队列,加入队列,对性能具有很大影响,如果队列设置较大时,max线程则很少会使用到,那么不妨考虑以下实现方式也行会更好些:

  • 当core线程数大于当前任务数时,可以创建新的线程;
  • 当core线程数小于当前执行的任务数时,而当前任务数小于max线程数时,则创建新的线程运行任务;
  • 当max线程数无法应付时,在将任务加入队列,如队列满时,在抛出RejectedExcutionException异常。

这样实现最大的利用了可用线程数,减少了创建队列加入队列的系统消耗。以下为代码实现:

自定义ThreadPoolExecutor:

public class ThreadPoolExecutorExtend extends java.util.concurrent.ThreadPoolExecutor{

    private final AtomicInteger atomicInt = new AtomicInteger(0);
    public ThreadPoolExecutorExtend(int corePoolSize, int maximumPoolSize,
            long keepAliveTime, TimeUnit unit, TaskQueue workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        workQueue.setExecutor(this);
    }
    @Override
    public void execute(Runnable command) {
        try{
            atomicInt.incrementAndGet();
            super.execute(command);
        }catch(Exception e){
            ((TaskQueue)super.getQueue()).offer(command);
        }
    }
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        atomicInt.decrementAndGet();
        super.afterExecute(r, t);
    }
    
    public int getSubmitTask(){
        return atomicInt.get();
    }
}

自定义LinkedBlockingQueue:

public class TaskQueue extends java.util.concurrent.LinkedBlockingQueue<Runnable>{

    private static final long serialVersionUID = 2804119236686921894L;

    private ThreadPoolExecutorExtend executor;
    
    public TaskQueue(int size) {
        super(size);
    }
    
    @Override
    public boolean offer(Runnable e) {
        // current task size
        int currentTask = executor.getPoolSize();
        if(currentTask < executor.getMaximumPoolSize()){
            return false;
        }
        return super.offer(e);
    }
    
    public void setExecutor(ThreadPoolExecutorExtend e){
        executor = e;
    }
    
}


测试类:

public class MyThreadPoolTest {
    
    public static void main(String[] args) {
        int corePoolSize = 5;
        int maximumPoolSize = 10;
        int keepAliveTime = 60;
        final ThreadPoolExecutorExtend pool = new ThreadPoolExecutorExtend(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new TaskQueue(5));
        for(int i=0;i<15;i++){
            pool.execute(new Runnable() {
                
                public void run() {
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
            });
            System.out.println("当前线程:"+pool.getPoolSize()+",当前队列数量:"+pool.getQueue().size());
        }
    }
}

运行结果如下:

当前线程:1,当前队列数量:0
当前线程:2,当前队列数量:0
当前线程:3,当前队列数量:0
当前线程:4,当前队列数量:0
当前线程:5,当前队列数量:0
当前线程:6,当前队列数量:0
当前线程:7,当前队列数量:0
当前线程:8,当前队列数量:0
当前线程:9,当前队列数量:0
当前线程:10,当前队列数量:0
当前线程:10,当前队列数量:1
当前线程:10,当前队列数量:2
当前线程:10,当前队列数量:3
当前线程:10,当前队列数量:4
当前线程:10,当前队列数量:5

可用将TaskQueue类中重写offer方法注释掉,再次运行测试类,看运行结果,即可看到区别。

转载于:https://my.oschina.net/u/3759047/blog/1595342

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值