1、简介
程序中需要创建大量生存周期很短暂的线程时,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长,使用线程池可以很好的提高性能。
使用线程池优势:
1、降低资源消耗:通过重用线程池中的线程,来减少每个线程创建和销毁的性能开销。
2、提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
对线程进行一些维护和管理,比如定时开始,周期执行,并发数控制等等。
3、提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
2、Executor框架和线程池实现原理
线程池在系统启动时创建大量空闲线程,程序将一个Runnable接口传给线程池,就会启动一条线程执行run方法,之行结束后不会死亡,而是再次返回到线程池中成为空闲状态,等待下一个Runable对象的run方法。线程池可以控制并发线程数量,防止大量并发是性能下降。
1、Executors工厂类产生线程池,有几个静态方法:
(1)newCachedThreadPool():创建一个具有缓存功能的线程池;
(2)newFixedThreadPool()创建可以重用、固定线程数的线程池;
(3)newSingeThread()只有单线程的线程池,类似于newFixedThreadPool传入1;
(4)newScheduledThreadPool()创建具有指定线程数的线程池
(5)newSingleThreadScheduledExecutor()创建只有一条线程的线程池,可以在指定延迟后执行任务。
前三个方法返回一个ExecutorService对象,该对象有三个方法:其中三个submit的参数不一样:Runnable对象提交给线程池;
2、使用线程池执行线程任务:
(1)调用Executors类创建ExecutorService对象,该对象代表一个线程池;
(2)创建Runnable或Callable实例;
(3)调用ExecutorService对象的submit方法提交实例;
(4)不提交实例时,调用shutdown方法关闭。
代码实例:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestThradPool { public static void main(String[] args) { // 创建固定线程数6的线程池 ExecutorService pool = Executors.newFixedThreadPool(6); // 提交2个线程 pool.submit(new TestThreadRunnable()); pool.submit(new TestThreadRunnable()); // 关闭线程池 pool.shutdown(); } }创建Runnable实例之后没有直接创建线程、启动线程来执行任务,通过线程池来执行任务。
3、Executor、ExecutorService、Executors区别:
1、Executor接口,接口Executor里面只有一个execute方法;
public interfaceExecutor { voidexecute(Runnable command); }2、ExecutorService接口,接口ExecutorService继承于Executor;
ExecutorService接口对 Executor 接口进行了扩展,提供了返回 Future 对象,终止,关闭线程池等方法。当调用 shutDown 方法时,线程池会停止接受新的任务,但会完成正在 pending 中的任务。
ExecutorService 的 shutDown 和 shutDownNow ,
(1)shutDown 不在接受新的线程,并且等待之前提交的线程都执行完在关闭,
(2)shutDownNow 直接关闭活跃状态的所有的线程,并返回等待中的线程。
public interfaceExecutorService extends Executor { voidshutdown(); List<Runnable>shutdownNow(); <T>Future<T> submit(Callable<T> task); }3、Executors类,
有多个方法,如:
public class Executors { public static ExecutorService newFixedThreadPool(int nThreads) { retur nnew ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); } publicstatic ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); public static ScheduledExecutorServicenewScheduledThreadPool(intcorePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } } }总之:Executor接口很简单,只有一个execute方法。ExecutorService是Executor的子接口,增加了一些常用的对线程的控制方法,之后使用线程池主要也是使用这些方法。AbstractExecutorService是一个抽象类。ThreadPoolExecutor就是实现了这个类。
public abstract class AbstractExecutorService implements ExecutorService {} public class ThreadPoolExecutor extends AbstractExecutorService {}4、常用线程池实现类ThreadPoolExecutor:
1、类ThreadPoolExecutor:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactorythreadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) thrownew NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize =maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime =unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }corePoolSize:线程池的大小;
maximumPoolSize:线程池最大大小;
keepAliveTime:线程活动保持时间;
TimeUnit:线程活动保持时间的单位;
workQueue:任务队列;
threadFactory:用于设置创建线程的工厂;
handler:饱和策略。
2、执行策略:
(1)调用ThreadPoolExecutor的execute提交线程,首先检查CorePool,如果CorePool内的线程小于CorePoolSize,新创建线程执行任务。
(2)如果当前CorePool内的线程大于等于CorePoolSize,那么将线程加入到BlockingQueue。
(3)如果不能加入BlockingQueue,在小于MaxPoolSize的情况下创建线程执行任务。
(4)如果线程数大于等于MaxPoolSize,那么执行拒绝策略。
3、实例:
import java.io.Serializable; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class TestEveryDay { public static void main(String[] args) { // 构造一个线程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), new ThreadPoolExecutor.DiscardOldestPolicy()); for (int i = 1; i <= 30; i++) { try{ // 产生一个任务,并将其加入到线程池 String task = "task@ " + i; System.out.println("put " + task); threadPool.execute(new ThreadPoolTask(task)); // 便于观察,等待一段时间 Thread.sleep(20); } catch (Exception e) { e.printStackTrace(); } } } } /** * * 线程池执行的任务 */ class ThreadPoolTask implements Runnable, Serializable { private static final long serialVersionUID = 0; private static int consumeTaskSleepTime = 2000; // 保存任务所需要的数据 private Object threadPoolTaskData; ThreadPoolTask(Object tasks) { this.threadPoolTaskData = tasks; } public void run() { // 处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句 System.out.println(Thread.currentThread().getName()); System.out.println("start.." + threadPoolTaskData); try {//便于观察,等待一段时间 Thread.sleep(consumeTaskSleepTime); } catch (Exception e) { e.printStackTrace(); } threadPoolTaskData = null; } public Object getTask() { return this.threadPoolTaskData; } }
参考:
https://blog.csdn.net/tuke_tuke/article/details/51353925
https://blog.csdn.net/qq_25806863/article/details/71126867
https://www.cnblogs.com/shamo89/p/6694133.html