线程池篇
建议您使用ThreadPoolExecutor类创建线程池,以便更好地管理线程池,并根据具体情况控制对线程池的分配
使用线程池可能会导致内存错误(oom )
获取核心数量
获取当前计算机的核心数。 Runtime.getRuntime ().availableProcessors );
趋势科技执行机构
线程池的最底层类ThreadPoolExecutor
threadpoolexecutorpoolexecutor=newthreadpoolexecutor (
2、
/*
* IO密集型CPU*2
* 1个CPU内核(逻辑处理器1 ),具有高CPU负载
*/
5、
60L、
TimeUnit.SECONDS,
//默认值为Integer.Max_Value
newlinkedblockingqueue(3)、
Executors.defaultThreadFactory ()
//*
* abortrejectedexecutionexception
* CallerRunsPolicy返回上一个线程,例如main线程
*磁盘策略放心新
* DiscardOldestPolicy放弃块队列中的第一个
*/
newthreadpoolexecutor.discardoldestpolicy ();
执行工具类
newworkstealingpool(1.8 )。
publicstaticexecutorservicenewworkstealingpool {
返回新论坛
(parallelism,
forkjoinpool.defaultforkjoinworkerthreadfactory、
null,true;
}
publicforkjoinpool (int parallelism,
forkjoinworkerthreadfactoryfactory、
uncaughtexceptionhandlerhandler,
布尔同步模式) {
检查并行列表(this )、
检查工厂(factory )、
汉德勒、
async模式? FIFO_QUEUE : LIFO_QUEUE,
' forkjoinpool-' nextpoolid '-worker-' );
checkPermission (;
}
privateforkjoinpool (int parallelism,
forkjoinworkerthreadfactoryfactory、
uncaughtexceptionhandlerhandler,
输入模式,
String workerNamePrefix ) {
this.workernameprefix=workernameprefix;
this.factory=factory;
this.ueh=handler;
this.config=(parallelismsmask );
longNP=(long ) (-parallelism; //offset ctl counts
this.CTL=(NPAC_shift ) AC_MASK )|) NPTC_shift ) TC_MASK;
}
//分支合并线程池
newFixedThreadPool
publicstaticexecutorservicenewfixedthreadpool {
returnnewthreadpoolexecutor (Nthreads,nthreads,
0L,TimeUnit.MILLISECONDS,
新链接块队列() );
}
创建的线程数是固定的,初始值和最大值为1
创建的阻塞队列没有上限
newCachedThre
adPoolpublic static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
带缓存的线程池数,当开始的时候是0,最大是Integer.MAX_VALUE
最长六十秒不被使用则被回收
newSingleThreadPool
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
创建一个单个的线程池(里面只有一个)
newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
创建一个带时间的线程池,使用的是DelayedWorkQueue拒绝阻塞队列
线程池的使用
execute():void
submit():Future
对无返回值的线程执行
try {
for (int i = 0; i < 9; i++) {
poolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "t");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
poolExecutor.shutdown();
}
对有返回值的线程执行
poolExecutor.submit(new FutureTask<>(() -> 1024)).get();
线程池的执行流程
首先来的线程任务开始开启小于等于corePoolSize的线程进行执行
如果有些线程还是没执行完,但是有新的任务来了,那么将会进入阻塞队列
如果阻塞队列满了,就会去开启新的线程来执行任务,线程<=MaxiNumPoolSize
当大于corePoolSize的线程在KeepAliveTime内没被使用则会被释放
如果开启了最大的线程还是有任务没有被执行,则会进行使用拒绝策略进行对新任务的拒绝
线程池具体参数的配置*
线程池的拒绝策略
当等待队列满了&线程池的最大线程数也达到了,当出现新的任务时,会执行拒绝策略
new ThreadPoolExecutor.CallerRunsPolicy()
abortPolicy 抛出RejectedExecutionException,阻止系统正常运行
CallerRunsPolicy 会回退到上一个线程(调用它的线程),比如main线程
DiscardPolicy 放弃新来的task,如果允许任务丢失,则是最好的一种策略
DiscardOldestPolicy 放弃阻塞队列中最开始的那个
上述策略皆实现了RejectedExecutionHandler接口
线程池最大线程数的设定
CPU密集型
CPU核数+1个线程的线程池
IO密集型
IO密集型任务线程并不是一直在执行任务,则应尽可能多的线程,CUP核数*2
CUP核数 / 1-阻塞系数 (阻塞系数在0.8~0.9之间)
比如8核CPU: 4/1-0.9 = 40