环境:JDK1.8
线程池中如果发生OOM后会如何?
线程池ThreadPoolExecutor当有线程发生了OOM,线程池会停止工作吗?
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2)) ;
pool.execute(() -> {
int i = 0 ;
for (;;) {
System.out.println(Thread.currentThread().getName() + ", i = " + (i++) + "," + pool) ;
try {
TimeUnit.MILLISECONDS.sleep(50) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
pool.execute(() -> {
int j = 0 ;
for (;;) {
System.out.println(Thread.currentThread().getName() + ", j = " + (j++) + "," + pool) ;
try {
TimeUnit.MILLISECONDS.sleep(50) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
pool.execute(() -> {
int k = 0 ;
List<byte[]> datas = new ArrayList<>() ;
for (;;) {
System.out.println(Thread.currentThread().getName() + ", k = " + (k++) + "," + pool) ;
byte[] buf = new byte[1024 * 100] ;
datas.add(buf) ;
try {
TimeUnit.MILLISECONDS.sleep(20) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
调整JVM运行内存
-Xms10m -Xmx10m
执行结果:
一开始3个线程交替执行,当其中一个线程发生OOM后,线程池中除了发生OOM的线程池不再继续工作外,其它的线程都继续工作。
自定义线程异常处理
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2), new ThreadFactory() {
private final ThreadGroup group = new ThreadGroup("Pack-Group");
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix = "pool-custom-thread-";
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("自定义线程异常处理:" + t.getName());
e.printStackTrace();
}});
return t;
}
});
线程池的拒绝策略
代码:
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.AbortPolicy()) ;
for (int i = 0; i < 6; i++) {
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
try {
TimeUnit.SECONDS.sleep(2) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;
1、AbortPolicy策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.AbortPolicy()) ;
当任务数 > 线程数 + 队列大小。超过的任务直接拒绝并且抛出异常。程序不会继续往下执行。
2、CallerRunsPolicy策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.CallerRunsPolicy()) ;
超过的任务会由调用者线程(执行execute方法所在的线程)执行任务。
3、DiscardOldestPolicy策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardOldestPolicy()) ;
for (int i = 0; i < 5; i++) {
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
try {
TimeUnit.SECONDS.sleep(2) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + ", 我是新入任务") ;
});
执行结果:
该策略会把任务队列中的列头删除,然后将自己放入队列(列尾)
4、DiscardPolicy策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardPolicy()) ;
for (int i = 0; i < 7; i++) {
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
try {
TimeUnit.SECONDS.sleep(2) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;
TimeUnit.SECONDS.sleep(5) ;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + ", 新任务执行") ;
});
执行结果:
该策略什么也不做,线程池能够正常继续执行下去。
自定义线程池
自定义线程池监控线程执行耗时时间
public class CustomThreadPool extends ThreadPoolExecutor {
public CustomThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
if (r instanceof Task) {
((Task) r).setStart(System.currentTimeMillis()) ;
System.out.println(t.getName() + ", 开始执行") ;
}
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (r instanceof Task) {
((Task) r).times();
}
}
public void execute(Task command) {
super.execute(command);
}
public static class Task implements Runnable {
private long start ;
private Callback callback ;
public Task(Callback callback) {
this.callback = callback ;
}
@Override
public void run() {
if (this.callback != null) {
this.callback.callback();
}
}
public void times() {
System.out.println(Thread.currentThread().getName() + " 执行耗时:" + (System.currentTimeMillis() - start) + "ms") ;
}
public void setStart(long start) {
this.start = start;
}
}
public static interface Callback {
void callback() ;
}
}
重写beforeExecute,afterExecute父类的这两个方法,线程执行前和执行后。
CustomThreadPool pool = new CustomThreadPool(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2)) ;
pool.execute(new Task(() -> {
try {
TimeUnit.SECONDS.sleep(1) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
})) ;
pool.execute(new Task(() -> {
try {
TimeUnit.SECONDS.sleep(3) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
})) ;
pool.execute(new Task(() -> {
try {
TimeUnit.SECONDS.sleep(2) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
})) ;
执行结果:
给个关注谢谢