java单例线程池配置_java(线程池的创建⽅式,和线程池的原
理)
1.为什么要使⽤线程池:
减少资源消耗,通过重复的使⽤已创建好的线程,避免了线程的频繁创建和销毁所造成的消耗
提⾼响应速度,当任务到达的时候,不需要再去创建,可以直接使⽤已经创建好的线程就能⽴即执⾏任务
提⾼线程的管理性,线程池可以统⼀管理线程的创建,销毁,分配,调优监控
2.使⽤线程池能解决什么问题
通过固定的⼏个线程为⼤量的操作服务,降低线程的频繁创建,销毁线程所需要消耗的时间,从⽽提⾼效应效率
3.线程池的创建⽅式
1.5版本通过Executors创建线程池
* @since 1.5
*@author Doug Lea*/
public classExecutors {/*** Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@codenThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@linkExecutorService#shutdown shutdown}.
*
*@paramnThreads the number of threads in the pool
*@returnthe newly created thread pool
*@throwsIllegalArgumentException if {@codenThreads <= 0}*/
public static ExecutorService newFixedThreadPool(intnThreads) {return newThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
}
public static ExecutorService newFixedThreadPool(intnThreads) {return newThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
}
查看:
ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
public ThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,
TimeUnit unit,
BlockingQueueworkQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize: 核⼼池的⼤⼩。 当有任务来之后,就会创建⼀个线程去执⾏任务,当线程池中的线程数⽬达到corePoolSize后,就会把到达的任务放到缓存队列当中
maximumPoolSize: 线程池最⼤线程数,它表⽰在线程池中最多能创建多少个线程;
keepAliveTime: 表⽰线程没有任务执⾏时最多保持多久时间会终⽌。
unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
1.创建⼀个定长的线程池
packagecom.thread;urrent.ExecutorService;urrent.Executors;public classExecutorsDemo {public static voidmain(String[] args) {
ExecutorService newFixedThreadPool= wFixedThreadPool(5);for (int i = 0; i < 100; i++) {final int temp =i;
@Overridepublic voidrun() {
System.out.println(Thread.currentThread().getName()+ ",i:" +temp);
}
});
}
}
}
上⾯创建了⼀个线程池⼤⼩为5的线程池,所有的任务都将由这5条线程执⾏,超出线程会在队列等待 核⼼线程数==最⼤线程数
定长线程池的⼤⼩最好根据系统资源进⾏设置。如Runtime().availableProcessors() 返回虚拟机最⼤的可⽤处理器数量
2.创建⼀个缓存线程池
public static voidcreateCachedPool() {
ExecutorService wCachedThreadPool();for (int i = 0; i < 1000000; i++) {final int temp =i;
@Overridepublic voidrun() {try{
Thread.sleep(100);
}catch(Exception e) {//TODO: handle exception
}
System.out.println(Thread.currentThread().getName()+ ",i:" +temp);
java线程池创建的四种}
});
}
}
缓存线程池,核⼼线程数为0 最⼤线程数Integer.MAX_VALUE ,如果有两个任务,第⼀个线程执⾏完了其中⼀个任务,则就继续⽤该线程执⾏下⼀个任务,如果该线程还在执⾏任务,则创建⼀个线程执⾏ 最⼤线程数是 可以认为是⽆限
3.创建⼀个定时周期线程池
public static voidcreateScheduledPool() {
ScheduledExecutorService newScheduledThreadPool= wScheduledThreadPool(5);for (int i = 0; i < 1000; i++) {final int temp =i;
newScheduledThreadPool.schedule(newRunnable() {public voidrun() {
System.out.println("i:" +temp);
}
},3, TimeUnit.SECONDS);
}
}
该线程池核⼼线程是5,最⼤线程池数Integer.MAX_VALUE,可以设置该线程池⾥⾯线程延迟多久执⾏任务,3表⽰3s以后再执⾏任务
4.创建⼀个单例线程
public static voidcreateSinglePool() {
ExecutorService wSingleThreadExecutor();for (int i = 0; i < 10; i++) {final int index =i;
@Overridepublic voidrun() {
System.out.println("index:" +index);try{
Thread.sleep(200);
}catch(Exception e) {//TODO: handle exception
}
}
});
}
}
public staticExecutorService newSingleThreadExecutor() {return newFinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue()));
}
最⼤线程数量等于核⼼线程数量,表⽰该线程池只会创建⼀个线程执⾏任务,执⾏该任务是有顺序的
4.线程池原理
提交⼀个任务到线程池中,线程池的处理流程如下:
1、判断线程池⾥的核⼼线程是否都在执⾏任务,如果不是(核⼼线程空闲或者还有核⼼线程没有被创建)则创建⼀个新的⼯作线程来执⾏任务。如果核⼼线程都在执⾏任务,则进⼊下个流程。
2、线程池判断⼯作队列是否已满,如果⼯作队列没有满,则将新提交的任务存储在这个⼯作队列⾥。如果⼯作队列满了,则进⼊下个流程。
3、判断线程池⾥的线程是否都处于⼯作状态,如果没有,则创建⼀个新的⼯作线程来执⾏任务。如果已经满了,则交给饱和策略来处理这个任务。
5.线程池的配置
要想合理的配置线程池,就必须⾸先分析任务特性,可以从以下⼏个⾓度来进⾏分析:
任务的性质:CPU密集型任务,IO密集型任务和混合型任务。
任务的优先级:⾼,中和低。
任务的执⾏时间:长,中和短。
任务的依赖性:是否依赖其他系统资源,如数据库连接。
任务性质不同的任务可以⽤不同规模的线程池分开处理。CPU密集型任务配置尽可能少的线程数量,如配置Ncpu+1个线程的线程池。IO密集型任务则由于需要等待IO操作,线程并不是⼀直在执⾏任务,
则配置尽可能多的线程,如2*Ncpu。混合型的任务,如果可以拆分,则将其拆分成⼀个CPU密集型任务和⼀个IO密集型任务,只要这两个任务执⾏的时间相差不是太⼤,那么分解后执⾏的吞吐率要⾼于串⾏执⾏的吞吐率,如果这两个任务执⾏时间相差太⼤,则没必要进⾏分解。可以通过Runtime().availableProcessors()⽅法获得当前设备的CPU个数。
优先级不同的任务可以使⽤优先级队列PriorityBlockingQueue来处理。它可以让优先级⾼的任务先得到执⾏,需要注意的是如果⼀直有优先级⾼的任务提交到队列⾥,那么优先级低的任务可能永远不能执⾏。
执⾏时间不同的任务可以交给不同规模的线程池来处理,或者也可以使⽤优先级队列,让执⾏时间短的任务先执⾏。
依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,如果等待的时间越长CPU空闲时间就越长,那么线程数应该设置越⼤,这样才能更好的利⽤CPU。
CPU密集型时,任务可以少配置线程数,⼤概和机器的cpu核数相当,这样可以使得每个线程都在执⾏任务
IO密集型时,⼤部分线程都阻塞,故需要多配置线程数,2*cpu核数
操作系统之名称解释:
某些进程花费了绝⼤多数时间在计算上,⽽其他则在等待I/O上花费了⼤多是时间,
前者称为计算密集型(CPU密集型)computer-bound,后者称为I/O密集型
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论