Java并发编程(6)-ThreadPoolExecutor解读(1)

版权声明: https://blog.csdn.net/pbrlovejava/article/details/83549904


更多关于Java并发编程的文章请点击这里:Java并发编程实践(0)-目录页


在上文中已经写过Executor线程调度框架的使用及几种线程池,它们是整个Java并发编程的核心内容;本文将继续讲解和Executor一样重要的自定义线程池,它能让我们自己去定义一个多线程的执行者拥有的线程核心数、最大线程数、空闲线存活时间等。
本篇总结自《Java并发编程实践》第八章 应用线程池 ,以及相关博客,想要更加深入了解的同学建议阅读该书。

一、什么是ThreadPoolExecutor

ThreadPoolExecutor位于java.util.concurrent并发包下,为一些Executor提供了基本的实现,在JDK1.5中由Executors中的工厂中的newCachedThreadPoolnewFixedThreadPoolnewScheduledThreadExecutor方法所返回。但在JDK1.7之后,不能通过Executors去获得ThreadPoolExecutor了,而是需要自己手动去定制。ThreadPoolExecutor是一个灵活的、健壮的池实现,允许用户进行各种各样的定制

二、ThreadPoolExecutor构造方法参数

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,//可不设置
                              RejectedExecutionHandler handler//可不设置)

在这里插入图片描述

  • core线程还能应付的,则不断的创建新的线程,但不会超出corePoolSize;
  • core线程无法应付,则将任务扔到队列里面,并且用core线程去执行;
  • 工作队列满了(意味着插入任务失败),则开始创建MAX线程,线程数达到MAX后,队列还一直是满的,则抛出RejectedExecutionException。

2.1、corePoolSize

核心线程池大小,当线程池中的线程数目小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。

2.1、maximumPoolSize

最大线程池大小,表示当前池中可以活跃的最大线程数目。

2.3、keepAliveTime

线程池中超过corePoolSize数目的空闲线程最大存活时间。

2.4、TimeUnit

keepAliveTime时间单位。可以设置为TimeUnit.MICROSECONDSTimeUnit.SECONDS等单位,分别表示毫秒和秒。

2.5、workQueue

阻塞任务队列,用以存储超出了corePoolSize的线程。

2.6、threadFactory

新建线程工厂。如果没有的话则使用系统默认的。

2.7、RejectedExecutionHandler

当提交任务数超过maxmumPoolSize与workQueue之和时,任务会交给RejectedExecutionHandler来处理。如果没有的话则使用系统默认的。

三、使用自己构造的ThreadPoolExecutor

测试类:

public class ThreadPoolExecutorDemo {

    @Test
    public void testThreadPoolExecutor(){
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                10,
                1000,
                TimeUnit.MICROSECONDS,
                new ArrayBlockingQueue<Runnable>(3),
                new MyThreadFactory(),
                new MyRejectedExecutionHandler());
        for (int i = 0; i < 35; i++) {

            int count = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    //模拟耗时操作
                    for (int j = 0; j < 500000; j++) {
                        //..
                    }
                    System.out.println("这是第"+count+"个线程在执行任务----"+Thread.currentThread().getName());

                }
            });
        }

    }

}

自定义的线程工厂类:

public class MyThreadFactory implements ThreadFactory {
    //线程标识器
    private AtomicInteger count  =  new AtomicInteger(0);

    @Override
    public Thread newThread(Runnable r) {
        //标识器自增1
        count.incrementAndGet();
        Thread thread = new Thread(r, "自定义线程(" + count + ")");
        return thread;
    }
}

自定义的异常处理类:

public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        //对超出的线程任务进行处理
        System.out.println("已处理...");
    }
}

执行后发现,当循环过多时,需要同时活跃的线程大于5个之后,新产生的线程进入阻塞队列中,当需要同时活跃的线程大于10个之后,新产生的线程将被自定义的MyRejectedExecutionHandler 处理。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/pbrlovejava/article/details/83549904