package com.app.mvc.test;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by jimin on 16/3/21.
*/
@Slf4j
public class TestThreadPool {
private static ConcurrentMap<Integer, ThreadPoolExecutor> threadPoolExecutorMap = Maps.newConcurrentMap();
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3000; i++) {
threadPoolExecutorMap.put(i, newDefaultExecutor());
}
log.info("start!");
for (int j = 1; j < 10; j++) {
for (int p = 1; p < 10; p++) {
try {
// 这里一定要使用execute, 而不要使用submit
// 原因是submit主要是为异步等待使用的, 返回FutureTask
// 如果使用submit,DiscardOldestPolicy中取出来的就是个FutureTask, 而不是普通的Runnable, 继续处理会阻塞进程
// 同时之前的进程如果已丢弃,这时会一直占着进程不释放
threadPoolExecutorMap.get(p).execute(new HttpWorker(p + "__" + j));
} catch (Throwable e) {
log.error("exception", e);
}
}
}
}
private static ThreadPoolExecutor newDefaultExecutor() {
return new ThreadPoolExecutor(1, // 核心池大小
2, // 最大线程数
1200, // 空闲等待时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<Runnable>(40), // 循环数组 + 指定大小
new DiscardOldestPolicy() // 最早的丢弃, 可以根据需要调整
);
}
/**
* 自定义rejectedExecution逻辑
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() {
}
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
HttpWorker httpWorker = (HttpWorker) e.getQueue().poll();
e.execute(r);
log.info("drop query: {}", httpWorker.getC());
}
}
}
/**
* 自定义Runnable, 方面在rejectedExecution时处理逻辑
*/
private static class HttpWorker implements Runnable {
private String c;
public HttpWorker(String c) {
this.c = c;
}
public String getC() {
return c;
}
@Override
public void run() {
long sum = 0;
for (int q = 0; q < 100000000; q++) {
sum += q;
}
log.info("c:{}, sum: {}", c, sum);
}
}
}