线程池
这里首先明白一个概念,什么是线程池(自己总结的,总感觉太偏向于概念性的内容反而不利于理解):线程池就是提前创建好固定数量的线程,有任务则执行,没有任务则进行等待。线程池解决了线程频繁创建与销毁在资源上的浪费,一次创建多次使用一次销毁。
优点
- 统一管理,更加方便
- 避免资源上的浪费
- 控制并发数量等
ThreadPoolExecutor
- 继承关系
- 构造器:重点(每个参数的意义)
/** 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)
- 流程图(画的不是那么准确,具体的执行过程代码体现)
- 代码体现(具体看注释,几乎每个步骤都有解释)
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就讲这么多,后边讲如何创建线程池,也就是创建线程池的四种方式