线程池:
image.png
Java中的线程池是通过Executor框架实现的,该框架中用到了Executor,Executors,ExecutorService,ThreadPoolExecutor
image.png image.png image.pngimage.png image.png image.png image.png线程池也有相应的辅助工具类 均在juc?
ThreadPoolExecutor 7参
image.png image.png image.png线程池底层原理
image.png image.png线程池拒绝策略
image.png
image.pngCallerRunsPolicy补充:从而降低流量
线程池使用规范
手写线程池?
/**
* 手写线程池
*/
public class MyThreadPoolExecutor {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
2, //核心线程数
5,//线程池最大数
1L,//多余corePoolSize可存活时间
TimeUnit.SECONDS,//keepaliveTime的单位
new LinkedBlockingQueue<>(3), //workQueue阻塞队列的数据结构,大小是3
Executors.defaultThreadFactory(),//创建线程的方式,使用默认既可
new ThreadPoolExecutor.AbortPolicy());//拒绝策略 默认AbortPolicy 当超过(maximumPoolSize+workQueue)时会抛出异常
for (int i = 1; i <= 9; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务");
});
}
}
}
如何合理配置线程池?
image.png第一种:由于I0密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如cPU核数*2
第二种:
image.png
死锁编码及定位分析
image.pngclass Resource implements Runnable {
private String lockA;
private String lockB;
public Resource(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run() {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "\t 自己持有的:" + lockA + "\t 尝试获得:" + lockB);
//为了效果明显 睡一会儿
try {
TimeUnit.SECONDS.sleep(1L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "\t 自己持有的:" + lockB + "\t 尝试获得:" + lockA);
}
}
}
}
public class DeadLock {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
new Thread(new Resource(lockA, lockB), "ThreadAAA").start();
new Thread(new Resource(lockB, lockA), "ThreadBBB").start();
}
}
通过 jps -l 找到进程编号
再通过jstack +进程编号 查找问题
image.png
网友评论