线程池
避免了线程不停的 开启 / 关闭 对系统资源的浪费,和对性能的损耗,方便统一管理线程,线程复用,控制并发数 事先准备好空的线程,有线程需要就分发给他,用完归还
线程池使用后 需要 手动 关闭 executorService.shutdown();
三大方法
使用 不建议使用 此处用于举例Executors.new方法
创建线程池
使用Executors.newSingleThreadExecutor();
创建只存在一个线程的线程池
public class Test01 {
public static void main(String[] args) {
test1();
}
public static void test1(){
//只存在一个线程的线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
for (int i = 0; i < 10; i++) {
//用池子创建线程
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行了");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();//关闭线程池
}
}
}
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
pool-1-thread-1执行了
线程名一直是 1
使用Executors.newFixedThreadPool(5);
创建指定线程数的线程池
public class Test01 {
public static void main(String[] args) {
test2();
}
public static void test2(){
//指定线程数的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 10; i++) {
//用池子创建线程
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"运行了");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();//关闭线程池
}
}
}
pool-1-thread-2运行了
pool-1-thread-5运行了
pool-1-thread-4运行了
pool-1-thread-4运行了
pool-1-thread-5运行了
pool-1-thread-5运行了
pool-1-thread-1运行了
pool-1-thread-3运行了
pool-1-thread-4运行了
pool-1-thread-2运行了
看到最大有五个线程同时执行
使用Executors.newCachedThreadPool();
创可变线程数的线程池
public class Test01 {
public static void main(String[] args) {
test3();
}
public static void test3(){
//可变大小线程池 最大值是Integer的最大长度21亿
ExecutorService executorService = Executors.newCachedThreadPool();
try {
for (int i = 0; i < 10; i++) {
//用池子创建线程
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"使用了");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();//关闭线程池
}
}
}
pool-1-thread-2使用了
pool-1-thread-6使用了
pool-1-thread-5使用了
pool-1-thread-4使用了
pool-1-thread-8使用了
pool-1-thread-1使用了
pool-1-thread-3使用了
pool-1-thread-10使用了
pool-1-thread-9使用了
pool-1-thread-7使用了
将循环次数改变为15
pool-1-thread-1使用了
pool-1-thread-5使用了
pool-1-thread-3使用了
pool-1-thread-8使用了
pool-1-thread-7使用了
pool-1-thread-4使用了
pool-1-thread-2使用了
pool-1-thread-6使用了
pool-1-thread-9使用了
pool-1-thread-10使用了
pool-1-thread-12使用了
pool-1-thread-13使用了
pool-1-thread-11使用了
pool-1-thread-6使用了
pool-1-thread-11使用了
可见线程大小不断变化
(七大参数
建议使用的线程池创建方式)*
三大方法的源码:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
注意:
new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
ThreadPoolExecutor:
public ThreadPoolExecutor(
int corePoolSize,//核心线程大小,无论何时一直存在的线程个数,(最小?)
int maximumPoolSize,//最大线程大小,最大同时存在的线程个数,可扩充的大小
long keepAliveTime,//超过多少时间未被调用将会释放
TimeUnit unit, //时间单位
BlockingQueue<Runnable> workQueue//阻塞队列类型Linked/Array允许等待的线程的大小
ThreadFactory threadFactory,//指定的线程创建工厂,保持不变用这个Executors.defaultThreadFactory()
RejectedExecutionHandler handler//拒绝策略 当超过(最大线程数+允许等待的线程的大小)的处理策略
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
创建正常线程池:
public class Test02 {
public static void main(String[] args) {
test01();
}
//创建真正的线程池
public static void test01(){
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(2,
5,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
//拒绝策略: 不处理,并抛出异常
new ThreadPoolExecutor.AbortPolicy()
);
try {
//总可容纳大小 = 5 + 3 现已超过 必然抛出异常
for (int i = 0; i < 10; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行了-");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPoolExecutor.shutdown();//关闭
}
}
}
pool-1-thread-1执行了
pool-1-thread-4执行了
pool-1-thread-5执行了
pool-1-thread-2执行了
pool-1-thread-3执行了
pool-1-thread-5执行了
pool-1-thread-4执行了
pool-1-thread-1执行了
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.xzb.pool
可见:
总可容纳大小 = 5(最大线程数) + 3(可等待线程数)
当线程数较少时并不会触发5应该在>2的方向徘徊
最大可同时执行5,超越时抛出异常->RejectedExecutionException
因为指定了拒绝策略为:new ThreadPoolExecutor.AbortPolicy()
四种拒绝策略
拒绝策略1:
不处理超过的线程,并抛出异常
new ThreadPoolExecutor.AbortPolicy()
结果:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.xzb.pool
拒绝策略2:
哪来的去哪里执行,如main来的就让main执行
new ThreadPoolExecutor.CallerRunsPolicy()
结果:
pool-1-thread-2执行了-
pool-1-thread-5执行了-
pool-1-thread-4执行了-
main执行了-
pool-1-thread-3执行了-
pool-1-thread-1执行了-
pool-1-thread-4执行了-
pool-1-thread-5执行了-
pool-1-thread-2执行了-
pool-1-thread-1执行了-
拒绝策略3:
丢弃超出的线程任务,忽略不执行
new ThreadPoolExecutor.DiscardPolicy()
结果:
pool-1-thread-3执行了-
pool-1-thread-5执行了-
pool-1-thread-3执行了-
pool-1-thread-2执行了-
pool-1-thread-3执行了-
pool-1-thread-4执行了-
pool-1-thread-1执行了-
pool-1-thread-5执行了-
拒绝策略4:
尝试替换掉 旧(最先执行)的 线程任务 不一定成功 不成功时和策略三相同
new ThreadPoolExecutor.DiscardOldestPolicy()
结果:
pool-1-thread-1执行了-
pool-1-thread-5执行了-
pool-1-thread-4执行了-
pool-1-thread-5执行了-
pool-1-thread-3执行了-
pool-1-thread-2执行了-
pool-1-thread-4执行了-
pool-1-thread-1执行了-