台州网站建设开发,网站建设合同印花税税率,作文网投稿,yole市场调研公司线程池
2.1 线程池思想 我们使用线程的时候就去创建一个线程#xff0c;这样实现起来非常简便#xff0c;但是就会有一个问题#xff1a; 如果并发的线程数量很多#xff0c;并且每个线程都是执行一个时间很短的任务就结束了#xff0c;这样频繁创建线程就会大大降低系统…线程池
2.1 线程池思想 我们使用线程的时候就去创建一个线程这样实现起来非常简便但是就会有一个问题 如果并发的线程数量很多并且每个线程都是执行一个时间很短的任务就结束了这样频繁创建线程就会大大降低系统的效率因为频繁创建线程和销毁线程需要时间。 那么有没有一种办法使得线程可以复用就是执行完一个任务并不被销毁而是可以继续执行其他的任务 在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池。 2.2 线程池概念 概念:其实就是一个容纳多个线程的容器其中的线程可以反复使用省去了频繁创建线程对象的操作无需反复创建线程而消耗过多资源。 由于线程池中有很多操作都是与优化资源相关的我们在这里就不多赘述。我们通过一张图来了解线程池的工作原理
合理利用线程池能够带来三个好处
降低资源消耗。减少了创建和销毁线程的次数每个工作线程都可以被重复利用可执行多个任务。提高响应速度。当任务到达时任务可以不需要的等到线程创建就能立即执行。提高线程的可管理性。可以根据系统的承受能力调整线程池中工作线线程的数目防止因为消耗过多的内存而把服务器累趴下(每个线程需要大约1MB内存线程开的越多消耗的内存也就越大最后死机)。
2.3 线程池的使用
2.3.1 概述
Java里面线程池的顶级接口是java.util.concurrent.Executor但是严格意义上讲Executor并不是一个线程池而只是一个执行线程的工具。真正的线程池接口是java.util.concurrent.ExecutorService。
要配置一个线程池是比较复杂的尤其是对于线程池的原理不是很清楚的情况下很有可能配置的线程池不是较优的因此在java.util.concurrent.Executors线程工厂类里面提供了一些静态工厂生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。
3.3.2 代码实现
3.3.2.1 基于Executors类创建线程静态方法实现
Executors类中有个创建线程池的方法如下
方法名描述public static ExecutorService newFixedThreadPool(int nThreads)创建一个固定大小的线程池因为采用无界的阻塞队列所以实际线程数量永远不会变化适用于负载较重的场景对当前线程数量进行限制。保证线程数可控不会造成线程过多导致系统负载更为严重public static newCachedThreadPool()用来创建一个可以无限扩大的线程池适用于负载较轻的场景执行短期异步任务。可以使得任务快速得到执行因为任务时间执行短可以很快结束也不会造成cpu过度切换public static newSingleThreadExecutor创建一个单线程的线程池适用于需要保证顺序执行各个任务。public static newScheduledThreadPool适用于执行延时或者周期性任务。
//使用线程池进行多线程代码执行
public class ExecutorsTest {public static void main(String[] args) {//1获取线程池对象//通过Executors工具类对应的静态方法 创建对应的线程池对象ExecutorService executorService Executors.newFixedThreadPool(2);//2创建执行的任务对象Runnable rnew Runnable() {Overridepublic void run() {//获取当前线程Thread thread Thread.currentThread();System.out.println(thread.getName()执行了任务);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(thread.getName()任务执行完毕回归线程池);}};//3向线程池提交任务executorService.submit(r);executorService.submit(r);executorService.submit(r);//4关闭线程池executorService.shutdown();}
}3.3.2.2基于ThreadPoolExecutor自定义线程池填入参数实现
ThreadPoolExecutor核心参数 Executor是线程池的顶级接口接口中只定义了一个方法 void execute(Runnable command)线程池的操作方法都是定义子在ExecutorService子接口中的所以说ExecutorService是线程池真正的接口。 ThreadPoolExecutor重要参数
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueueRunnable workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}- corePoolSize 线程池核心线程数
- maximumPoolSize线程池最大数
- keepAliveTime 空闲线程存活时间
- unit 时间单位
- workQueue 线程池所使用的缓冲队列
- threadFactory线程池创建线程使用的工厂
- handler 线程池对拒绝任务的处理策略线程池四种拒绝策略 线程四种拒绝策略当工作任务大于最大线程 阻塞队列会执行阻塞队列。 拒绝策略类型说明1ThreadPoolExecutor.AbortPolicy默认拒绝策略拒绝任务并抛出任务2ThreadPoolExecutor.CallerRunsPolicy使用调用线程直接运行任务3ThreadPoolExecutor.DiscardPolicy直接拒绝任务不抛出错误4ThreadPoolExecutor.DiscardOldestPolicy触发拒绝策略只要还有任务新增一直会丢弃阻塞队列的最老的任务并将新的任务加入
public class MyThreadPoolTest {public static void main(String[] args) {//就是通过创建ThreadPoolExecutor对象 调用构造方法传入参数实现自定义线程池//如果想对线程池添加额外功能可以通过继承ThreadPoolExecutor类 实现//但是必须通过构造方法传入参数 才能实现线程池功能int initSize3;//初始化线程池中线程个数int maxSize5;//任务提交后没有空闲线程 扩容后线程池中线程最大个数int keepTime0;//线程池中线程最大空闲时间(超过后会回收直至线程数到达初始化大小)0代表不回收TimeUnit timeUnitTimeUnit.MILLISECONDS;//空闲时间单位 毫秒枚举类型TimeUnit.SECONDS代表分钟BlockingQueueRunnable queuenew LinkedBlockingQueue();ThreadFactory threadFactoryExecutors.defaultThreadFactory();//默认线程创建工厂RejectedExecutionHandler handler new ThreadPoolExecutor.AbortPolicy();//默认拒绝策略ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(initSize, maxSize, keepTime, timeUnit, queue, threadFactory, handler);Runnable rnew Runnable() {Overridepublic void run() {//获取当前线程Thread thread Thread.currentThread();System.out.println(thread.getName()执行了任务);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(thread.getName()任务执行完毕回归线程池);}};threadPoolExecutor.submit(r);threadPoolExecutor.submit(r);threadPoolExecutor.submit(r);threadPoolExecutor.shutdown();}
}