熟悉Java多线程编程的同窗都知道,当咱们线程建立过多时,容易引起内存溢出,所以咱们就有必要使用线程池的技术了。java
目录数据库
1 线程池的优点编程
2 线程池的使用数组
4 线程池的参数多线程
5 功能线程池ide
5.2 定时线程池(ScheduledThreadPool )
5.4 单线程化线程池(SingleThreadExecutor)
整体来讲,线程池有以下的优点:
(1)下降资源消耗。经过重复利用已建立的线程下降线程建立和销毁形成的消耗。
(2)提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。
(3)提升线程的可管理性。线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,使用线程池能够进行统一的分配,调优和监控。
线程池的真正实现类是ThreadPoolExecutor,其构造方法有以下4种:
1. public ThreadPoolExecutor(int corePoolSize, 2. int maximumPoolSize, 3. long keepAliveTime, 4. TimeUnit unit, 5. BlockingQueue<Runnable> workQueue) { 6. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 7. Executors.defaultThreadFactory(), defaultHandler); 8. } 10. public ThreadPoolExecutor(int corePoolSize, 11. int maximumPoolSize, 12. long keepAliveTime, 13. TimeUnit unit, 14. BlockingQueue<Runnable> workQueue, 15. ThreadFactory threadFactory) { 16. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 17. threadFactory, defaultHandler); 18. } 20. public ThreadPoolExecutor(int corePoolSize, 21. int maximumPoolSize, 22. long keepAliveTime, 23. TimeUnit unit, 24. BlockingQueue<Runnable> workQueue, 25. RejectedExecutionHandler handler) { 26. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 27. Executors.defaultThreadFactory(), handler); 28. } 30. public ThreadPoolExecutor(int corePoolSize, 31. int maximumPoolSize, 32. long keepAliveTime, 33. TimeUnit unit, 34. BlockingQueue<Runnable> workQueue, 35. ThreadFactory threadFactory, 36. RejectedExecutionHandler handler) { 37. if (corePoolSize < 0 || 38. maximumPoolSize <= 0 || 39. maximumPoolSize < corePoolSize || 40. keepAliveTime < 0) 41. throw new IllegalArgumentException(); 42. if (workQueue == null || threadFactory == null || handler == null) 43. throw new NullPointerException(); 44. this.corePoolSize = corePoolSize; 45. this.maximumPoolSize = maximumPoolSize; 46. this.workQueue = workQueue; 47. this.keepAliveTime = unit.toNanos(keepAliveTime); 48. this.threadFactory = threadFactory; 49. this.handler = handler; 50. }
能够看到,其须要以下几个参数:
线程池的使用流程以下:
1. // 建立线程池 2. ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, 3. MAXIMUM_POOL_SIZE, 4. KEEP_ALIVE, 5. TimeUnit.SECONDS, 6. sPoolWorkQueue, 7. sThreadFactory); 8. // 向线程池提交任务 9. threadPool.execute(new Runnable() { 10. @Override 11. public void run() { 12. ... // 线程执行的任务 13. } 14. }); 15. // 关闭线程池 16. threadPool.shutdown(); // 设置线程池的状态为SHUTDOWN,而后中断全部没有正在执行任务的线程 17. threadPool.shutdownNow(); // 设置线程池的状态为 STOP,而后尝试中止全部的正在执行或暂停任务的线程,并返回等待执行任务的列表
下面来描述一下线程池工做的原理,同时对上面的参数有一个更深的了解。其工做原理流程图以下:
经过上图,相信你们已经对全部参数有个了解了。下面再对任务队列、线程工厂和拒绝策略作更多的说明。
任务队列是基于阻塞队列实现的,即采用生产者消费者模式,在Java中须要实现BlockingQueue接口。但Java已经为咱们提供了7种阻塞队列的实现:
注意有界队列和无界队列的区别:若是使用有界队列,当队列饱和时并超过最大线程数时就会执行拒绝策略;而若是使用无界队列,由于任务队列永远均可以添加任务,因此设置maximumPoolSize没有任何意义。
线程工厂指定建立线程的方式,须要实现ThreadFactory接口,并实现newThread(Runnable r)方法。该参数能够不用指定,Executors框架已经为咱们实现了一个默认的线程工厂:
1. /** 2. * The default thread factory. 3. */ 4. private static class DefaultThreadFactory implements ThreadFactory { 5. private static final AtomicInteger poolNumber = new AtomicInteger(1); 6. private final ThreadGroup group; 7. private final AtomicInteger threadNumber = new AtomicInteger(1); 8. private final String namePrefix; 10. DefaultThreadFactory() { 11. SecurityManager s = System.getSecurityManager(); 12. group = (s != null) ? s.getThreadGroup() : 13. Thread.currentThread().getThreadGroup(); 14. namePrefix = "pool-" + 15. poolNumber.getAndIncrement() + 16. "-thread-"; 17. } 19. public Thread newThread(Runnable r) { 20. Thread t = new Thread(group, r, 21. namePrefix + threadNumber.getAndIncrement(), 22. 0); 23. if (t.isDaemon()) 24. t.setDaemon(false); 25. if (t.getPriority() != Thread.NORM_PRIORITY) 26. t.setPriority(Thread.NORM_PRIORITY); 27. return t; 28. } 29. }
当线程池的线程数达到最大线程数时,须要执行拒绝策略。拒绝策略须要实现RejectedExecutionHandler接口,并实现rejectedExecution(Runnable r, ThreadPoolExecutor executor)方法。不过Executors框架已经为咱们实现了4种拒绝策略:
嫌上面使用线程池的方法太麻烦?其实Executors已经为咱们封装好了4种常见的功能线程池,以下:
建立方法的源码:
1. public static ExecutorService newFixedThreadPool(int nThreads) { 2. return new ThreadPoolExecutor(nThreads, nThreads, 3. 0L, TimeUnit.MILLISECONDS, 4. new LinkedBlockingQueue<Runnable>()); 5. } 6. public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { 7. return new ThreadPoolExecutor(nThreads, nThreads, 8. 0L, TimeUnit.MILLISECONDS, 9. new LinkedBlockingQueue<Runnable>(), 10. threadFactory); 11. }
使用示例:
1. // 1. 建立定长线程池对象 & 设置线程池线程数量固定为3 2. ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); 3. // 2. 建立好Runnable类线程对象 & 需执行的任务 4. Runnable task =new Runnable(){ 5. public void run() { 6. System.out.println("执行任务啦"); 7. } 8. }; 9. // 3. 向线程池提交任务 10. fixedThreadPool.execute(task);
建立方法的源码:
1. private static final long DEFAULT_KEEPALIVE_MILLIS = 10L; 3. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { 4. return new ScheduledThreadPoolExecutor(corePoolSize); 5. } 6. public ScheduledThreadPoolExecutor(int corePoolSize) { 7. super(corePoolSize, Integer.MAX_VALUE, 8. DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, 9. new DelayedWorkQueue()); 10. } 12. public static ScheduledExecutorService newScheduledThreadPool( 13. int corePoolSize, ThreadFactory threadFactory) { 14. return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); 15. } 16. public ScheduledThreadPoolExecutor(int corePoolSize, 17. ThreadFactory threadFactory) { 18. super(corePoolSize, Integer.MAX_VALUE, 19. DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, 20. new DelayedWorkQueue(), threadFactory); 21. }
使用示例:
1. // 1. 建立 定时线程池对象 & 设置线程池线程数量固定为5 2. ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); 3. // 2. 建立好Runnable类线程对象 & 需执行的任务 4. Runnable task =new Runnable(){ 5. public void run() { 6. System.out.println("执行任务啦"); 7. } 8. }; 9. // 3. 向线程池提交任务 10. scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务 11. scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务
建立方法的源码:
1. public static ExecutorService newCachedThreadPool() { 2. return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 3. 60L, TimeUnit.SECONDS, 4. new SynchronousQueue<Runnable>()); 5. } 6. public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { 7. return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 8. 60L, TimeUnit.SECONDS, 9. new SynchronousQueue<Runnable>(), 10. threadFactory); 11. }
使用示例:
1. // 1. 建立可缓存线程池对象 2. ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); 3. // 2. 建立好Runnable类线程对象 & 需执行的任务 4. Runnable task =new Runnable(){ 5. public void run() { 6. System.out.println("执行任务啦"); 7. } 8. }; 9. // 3. 向线程池提交任务 10. cachedThreadPool.execute(task);
建立方法的源码:
1. public static ExecutorService newSingleThreadExecutor() { 2. return new FinalizableDelegatedExecutorService 3. (new ThreadPoolExecutor(1, 1, 4. 0L, TimeUnit.MILLISECONDS, 5. new LinkedBlockingQueue<Runnable>())); 6. } 7. public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { 8. return new FinalizableDelegatedExecutorService 9. (new ThreadPoolExecutor(1, 1, 10. 0L, TimeUnit.MILLISECONDS, 11. new LinkedBlockingQueue<Runnable>(), 12. threadFactory)); 13. }
使用示例:
1. // 1. 建立单线程化线程池 2. ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); 3. // 2. 建立好Runnable类线程对象 & 需执行的任务 4. Runnable task =new Runnable(){ 5. public void run() { 6. System.out.println("执行任务啦"); 7. } 8. }; 9. // 3. 向线程池提交任务 10. singleThreadExecutor.execute(task);
Executors的4个功能线程池虽然方便,但如今已经不建议使用了,而是建议直接经过使用ThreadPoolExecutor的方式,这样的处理方式让写的同窗更加明确线程池的运行规则,规避资源耗尽的风险。
其实Executors的4个功能线程有以下弊端: