线程池的分类
Executor框架的最顶层实现是ThreadPoolExecutor类。
Executors工厂类中提供的:
1、newSingleThreadExecutor
2、newScheduledThreadPool
3、newFixedThreadPool
4、newCachedThreadPool
其实也只是ThreadPoolExecutor的构造函数参数不同而已。
通过传入不同的参数,就可以构造出适用于不同应用场景下的线程池。
corePoolSize: 核心池的大小。 当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中
maximumPoolSize: 线程池最大线程数,它表示在线程池中最多能创建多少个线程;
keepAliveTime: 表示线程没有任务执行时最多保持多久时间会终止。
unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性
参数分析与execute源码解析
执行任务时,通过下面源代码可以得出以下结论
1、如果线程池中线程数量 < 核心线程数,新建一个线程执行任务;
2、如果线程池中线程数量 >= 核心线程数,则将任务放入任务队列
3、如果线程池中线程数量 >= 核心线程数 且 < maxPoolSize,且任务队列满了,则创建新的线程;
4、如果线程池中线程数量 > 核心线程数,当线程空闲时间超过了keepalive时,则会销毁线程;由此可见线程5、池的队列如果是无界队列,那么设置线程池最大数量是无效的;
6、如果线程池中的任务队列满了,而且线程数达到了maxPoolSize,并且没有空闲的线程可以执行新的任务,这时候再提交任务就会执行拒绝策略
java提供的拒绝策略
AbortPolicy,直接抛出RejectedExecutionException
CallerRunsPolicy,直接在主线程中执行
DiscardOldestPolicy 抛弃队列头的任务,然后重试execute。
DiscardPolicy,直接丢弃
newCachedThreadPool
newCachedThreadPool是一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
package com.enumclass.demo.linepool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClsaaName: TestNewCashedThreadPOOL
* @auther: LT
* @Date: 2019/4/22 11:37
* @Description: TODO
* @version:
*/
public class TestNewCashedThreadPOOL {
public static void main(String[] args) {
//创建一个可缓存线程池---最大线程数无限大的 也可以做线程服用
// 无限大小线程池 jvm自动回收
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int temp = i;
newCachedThreadPool.execute(new Runnable() {
public void run() {
//执行任务
System.out.println(Thread.currentThread().getName() + "," + temp);
}
});
}
}
}
运行结果:
不管你循环多少次,10次就有10个线程来处理,没有进行线程的服用。线程数是无限大的
newFixedThreadPool
newFixedThreadPool是一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
代码演示:
package com.enumclass.demo.linepool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClsaaName: TestNewCashedThreadPOOL
* @auther: luotao
* @Date: 2019/4/22 11:37
* @Description: TODO
* @version:
*/
public class TestNewFixedThreadPOOL {
public static void main(String[] args) {
//创建一个定长线程池 线程总数量为5,通过这5个线程一直在服用
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int temp = i;
newFixedThreadPool.execute(new Runnable() {
public void run() {
//执行任务
System.out.println(Thread.currentThread().getName() + "," + temp);
}
});
}
}
}
运行结果:
循环10次,但是线程是5个一直是在复用这5个线程。
newScheduledThreadPool
newScheduledThreadPool是一个定长线程池,支持定时及周期性任务执行。
代码演示:
package com.enumclass.demo.linepool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @ClsaaName: TestNewCashedThreadPOOL
* @auther: luotao
* @Date: 2019/4/22 11:37
* @Description: TODO
* @version:
*/
public class TestNewScheduledThreadPOOL {
public static void main(String[] args) {
//创建一个定长线程池
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
newScheduledThreadPool.schedule(new Runnable() {
public void run() {
//执行任务
System.out.println(Thread.currentThread().getName() + "," + temp);
}
}, 3, TimeUnit.SECONDS); //3秒之后执行任务调度
}
}
}
运行结果:
在等待3秒后执行,定义的线程数量为3个
newSingleThreadExecutor
newSingleThreadExecutor是一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
代码演示:
package com.enumclass.demo.linepool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClsaaName: TestNewCashedThreadPOOL
* @auther: luotao
* @Date: 2019/4/22 11:37
* @Description: TODO
* @version:
*/
public class TestNewSingleThreadExecutor {
public static void main(String[] args) {
//创建一个单线程
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int temp = i;
//execute相当于start线程
newSingleThreadExecutor.execute(new Runnable() {
public void run() {
//执行任务
System.out.println(Thread.currentThread().getName() + "," + temp);
}
});
}
newSingleThreadExecutor.shutdown();
}
}
执行结果:
只有一个唯一线程在进行复用。