线程池

这里首先明白一个概念,什么是线程池(自己总结的,总感觉太偏向于概念性的内容反而不利于理解):线程池就是提前创建好固定数量的线程,有任务则执行,没有任务则进行等待。线程池解决了线程频繁创建与销毁在资源上的浪费,一次创建多次使用一次销毁。

优点

  1. 统一管理,更加方便
  2. 避免资源上的浪费
  3. 控制并发数量等

ThreadPoolExecutor

  1. 继承关系
  2. 构造器:重点(每个参数的意义)
    /** corePoolSize - 池中所保存的线程数,包括空闲线程。 maximumPoolSize - 池中允许的最大线程数。 keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。 unit - keepAliveTime 参数的时间单位。 workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。 */
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 
    
    /** handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。 */
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
    
    /** threadFactory - 执行程序创建新线程时使用的工厂。 */
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
    
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
    
  3. 流程图(画的不是那么准确,具体的执行过程代码体现)
  4. 代码体现(具体看注释,几乎每个步骤都有解释)
    package threadpool;
    
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /** * @ClassName ThreadPoolExecutorDemo * @Description: TODO * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 8:50 * @Version v1.0 */
    public class ThreadPoolExecutorDemo {
        public static void main(String[] args) {
            ThreadPoolExecutor pool = null;
            try {
                /** * 创建线程池 * 参数意义: * corePoolSize:核心线程数(无任务时保持的线程数量) * maximumPoolSize:最大线程数 * keepAliveTime:新创建的线程无任务执行时存活的最大时间 * unit:时间类型 * workQueue:阻塞队列,无参数:无界队列 有参数:有界队列 */
                pool =
                        new ThreadPoolExecutor(1, 3, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3));
    
                MyRunnable myRunnable = new MyRunnable();
    
                System.out.println("--活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                pool.execute(myRunnable);
                System.out.println("--活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行 注意:队列已满(已经存在三个任务)
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                pool.execute(myRunnable);// 这时再执行任务时,依然往队列中添加任务,触发创建线程机制
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,触发创建线程机制,注意:达到了核心线程的数量 */
                pool.execute(myRunnable);
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,抛出异常 * RejectedExecutionException */
                pool.execute(myRunnable);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("线程数量以达最大值,请勿继续添加任务!!!");
            } finally {
                /** * 关闭线程池 */
                if (pool != null)
                    pool.shutdown();
            }
    
        }
    }
    
    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "开始执行...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // System.out.println(Thread.currentThread().getName() + "结束执行...");
        }
    }	
    
    package threadpool;
    
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.RejectedExecutionHandler;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /** * @ClassName ThreadPoolExecutorDemo * @Description: TODO * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 8:50 * @Version v1.0 */
    public class ThreadPoolExecutorDemo2 {
        public static void main(String[] args) {
            ThreadPoolExecutor pool = null;
            try {
                /** * 创建线程池 * 参数意义: * corePoolSize:核心线程数(无任务时保持的线程数量) * maximumPoolSize:最大线程数 * keepAliveTime:新创建的线程无任务执行时存活的最大时间 * unit:时间类型 * workQueue:阻塞队列,无参数:无界队列 有参数:有界队列 * handler:当线程池不能处理任务时做的处理,线程池自己会调用这个处理 */
                pool =
                        new ThreadPoolExecutor(1, 3, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), new RejectedExecutionHandler() {
                            @Override
                            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                                executor.shutdown();
                                System.out.println("线程数量以达最大值,请勿继续添加任务!!!");
                            }
                        });
    
                MyRunnable myRunnable = new MyRunnable();
    
                pool.execute(myRunnable);
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行 注意:队列已满(已经存在三个任务)
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                pool.execute(myRunnable);// 这时再执行任务时,依然往队列中添加任务,触发创建线程机制
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,触发创建线程机制,注意:达到了核心线程的数量 */
                pool.execute(myRunnable);
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,抛出异常 * RejectedExecutionException */
                pool.execute(myRunnable);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    package threadpool;
    
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /** * @ClassName ThreadPoolExecutorDemo * @Description: TODO * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 8:50 * @Version v1.0 */
    public class ThreadPoolExecutorDemo3 {
        public static void main(String[] args) {
            ThreadPoolExecutor pool = null;
            try {
                /** * 创建线程池 * 参数意义: * corePoolSize:核心线程数(无任务时保持的线程数量) * maximumPoolSize:最大线程数 * keepAliveTime:新创建的线程无任务执行时存活的最大时间 * unit:时间类型 * workQueue:阻塞队列,无参数:无界队列 有参数:有界队列 * threadFactory:执行程序创建新线程时使用的工厂 */
                pool =
                        new ThreadPoolExecutor(1, 3, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), new ThreadFactory() {
                            @Override
                            public Thread newThread(Runnable r) {
                                Thread thread = new Thread(r);
                                System.out.println("线程创建成功!!!");
                                return thread;
                            }
                        });
    
                MyRunnable myRunnable = new MyRunnable();
    
                pool.execute(myRunnable);
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行
                pool.execute(myRunnable);// 依然只有核心线程在执行 注意:队列已满(已经存在三个任务)
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                pool.execute(myRunnable);// 这时再执行任务时,依然往队列中添加任务,触发创建线程机制
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,触发创建线程机制,注意:达到了核心线程的数量 */
                pool.execute(myRunnable);
                System.out.println("活跃线程数:" + pool.getActiveCount() + " 队列长度:" + pool.getQueue().size());
                /** * 再次添加任务,抛出异常 * RejectedExecutionException */
                // pool.execute(myRunnable);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (pool != null)
                    pool.shutdown();
            }
        }
    }
    

ThreadPooExecutor就讲这么多,后边讲如何创建线程池,也就是创建线程池的四种方式