1.首先定义一个自己的线程类
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* @author muYou
* @info 定制化并发线程池
* @date 2019-07-30
*/
public class MyExecutor extends ThreadPoolExecutor {
private ConcurrentHashMap<String,Date> startTime;
/**
* @info the method overrid father
* @param corePoolSize
* @param maximumPoolSize
* @param keepAliveTime
* @param unit
* @param workQueue
* @param threadFactory
* @param handler
*/
public MyExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
startTime = new ConcurrentHashMap<>();
}
/**
* 覆盖shutdown()方法。将关于已执行的任务,
* 正在运行的任务和待处理的任务信息持久化。
* 然后,使用super关键字调用父类的shutdown()方法。
*/
@Override
public void shutdown() {
System.out.printf("threadPoolExecutor: Going to shutdown.\n");
System.out.printf("threadPoolExecutor: 已执行的任务(Executed ):%d\n",getCompletedTaskCount());
System.out.printf("threadPoolExecutor: 运行任务(Running ):%d\n",getActiveCount());
System.out.printf("threadPoolExecutor: 挂起的任务(Pending ):%d\n",getQueue().size());
super.shutdown();
}
/**
* 覆盖shutdownNow()方法。将关于已执行的任务,
* 正在运行的任务和待处理的任务信息持久化。
* 然后,使用super关键字调用父类的shutdownNow()方法。
* @return
*/
@Override
public List<Runnable> shutdownNow() {
System.out.printf("threadPoolExecutor: 立即关闭.\n");
System.out.printf("threadPoolExecutor: 已执行的任务(Executed ): %d\n",getCompletedTaskCount());
System.out.printf("threadPoolExecutor: 运行任务(Running ): %d\n",getActiveCount());
System.out.printf("threadPoolExecutor: 挂起的任务(Pending ): %d\n",getQueue().size());
return super.shutdownNow();
}
/**
* 覆盖beforeExecute()方法。写入一条信息
* (将要执行任务的线程名和任务的哈希编码)到控制台。
* 在Map中,使用这个任务的哈希编码作为key,存储开始日期。
*/
@Override
protected void beforeExecute(Thread t, Runnable r) {
System.out.printf("threadPoolExecutor: A task is beginning: %s : %s\n",t.getName(),r.hashCode());
startTime.put(String.valueOf(r.hashCode()), new Date());
super.beforeExecute(t, r);
}
/**
* 覆盖afterExecute()方法。将任务的结果和计算任务的运行时间
* (将当前时间减去存储在HashMap中的任务的开始时间)
* 的信息写入到控制台。
* @param r
* @param t
*/
@Override
protected void afterExecute(Runnable r, Throwable t) {
Future<?> result = (Future<?>) r;
System.out.println("==========================\n");
System.out.printf("threadPoolExecutor: A task is finishing.\n");
try {
System.out.printf("threadPoolExecutor: Result: %s\n",result.get());
Date startDate = startTime.remove(String.valueOf(r.hashCode()));
Date finishDate = new Date();
long diff=finishDate.getTime()-startDate.getTime();
System.out.printf("threadPoolExecutor: 持续时间(Duration)ms: %d\n",diff);
System.out.printf("*********************************\n");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
super.afterExecute(r, t);
}
}
4.调用
// 线程池满了。继续往里面添加。
static RejectedExecutionHandler handler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()){
System.out.println("线程池已满");
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
public void 实现类方法(){
CountDownLatch cdl = new CountDownLatch(1);
final Future<Boolean> submit = myExecutor.submit(new
TaskResult(employeeId,companyId,cdl));
final Boolean result = submit.get();
//TODO 闭锁等待
cdl.await();
}
/**
* 线程池内部类
*/
class TaskResult implements Callable<Boolean> {
private Long userId;
private Long companyId;
private CountDownLatch cdl;
public TaskResult(Long userId,Long companyId,CountDownLatch cdl) {
this.userId = userId;
this.companyId = companyId;
this.cdl = cdl;
}
@Override
public Boolean call() {
try {
业务方法
return true;
}catch (Exception e){
log.error("执行线程池任务时异常{},{}",e,e.getMessage());
e.printStackTrace();
}finally {
cdl.countDown();
}
return false;
}
}