JUC并发编程—线程池学习
好处:
1、降低资源的消耗;2、提高相应的速度;3、方便管理
1、线程池创建的三大方法
package com.zkw.JUC并发编程.线程池;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// Executors 工具类、3大方法
public class Demo01 {
public static void main(String[] args) {
//ExecutorService threadPool = Executors.newSingleThreadExecutor();// 单个线程
// ExecutorService threadPool = Executors.newFixedThreadPool(5);// 创建一个固定大小的线程池
ExecutorService threadPool = Executors.newCachedThreadPool();// 创建一个 可伸缩的,遇强则强的线程池
try {
for (int i = 0; i < 100; i++) {
// 使用了线程池之后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
2、7大参数
源码分析
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,//约为20亿
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
//本质 ThreadPoolExecutor()
public ThreadPoolExecutor(int corePoolSize,// 核心线程池大小
int maximumPoolSize, //最大核心线程池大小
long keepAliveTime,// 超时没有人调用就会释放
TimeUnit unit, // 超时单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory,// 线程工厂,创建线程的,一般不用
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
package com.zkw.JUC并发编程.线程池;
import java.util.concurrent.*;
/**
* 报出的异常:java.util.concurrent.RejectedExecutionException
* 1、new ThreadPoolExecutor.AbortPolicy() //满了,还有人又进来,不处理,抛出异常
* 2、new ThreadPoolExecutor.CallerRunsPolicy() //满了,还有人来,哪里来的去哪里
* 3、new ThreadPoolExecutor.DiscardPolicy() //队列满了,还有要进的,不会抛出异常,会把任务丢掉
* 4、new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,还有要进的,丢弃队列最前面的,然后重新提交被拒绝的
*/
public class Demo01 {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
try {
for (int i =1; i <= 9; i++) {
threadPool.execute(()->{
//拒绝策略被执行的条件是,队列和线程池全满的时候
//加一个延时就是为了让里边的线程先在里边等着,这样才更容易看出拒绝策略被执行过
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
3、四中策略
- 报出的异常:
java.util.concurrent.RejectedExecutionException
- 1、
new ThreadPoolExecutor.AbortPolicy()
满了,还有人又进来,不处理,抛出异常 - 2、
new ThreadPoolExecutor.CallerRunsPolicy()
满了,还有人来,哪里来的去哪里 - 3、
new ThreadPoolExecutor.DiscardPolicy()
队列满了,还有要进的,不会抛出异常,会把任务丢掉 - 4、
new ThreadPoolExecutor.DiscardOldestPolicy()
队列满了,还有要进的,丢弃队列最前面的,然后重新提交被拒绝的
小结拓展
了解IO密集型、CPU密集型
池的大小到底该如何定义?
Runtime.getRuntime().availableProcessors()
获取电脑的CPU是几核的
1、CPU密集型,几核,就是几,可以保持CPU的效率最高!
2、IO密集型, 最大线程数 = 2* 判断程序中十分耗IO的线程