代码改变世界

第一章:多线程十一之调度器钩子方法

2023-10-25 21:58  阿方技术圈  阅读(103)  评论(0)    收藏  举报

ThreadPoolExecutor线程池调度器为每个任务执行前后都提供了钩子方法。ThreadPoolExecutor类提供了三个钩子方法(空方法),这三个钩子方法一般用作被子类重写,具体如下:

     //任务执行之前的钩子方法(前钩子)
     protected void beforeExecute(Thread t, Runnable r)   { }
     //任务执行之后的钩子方法(后钩子)
     protected void afterExecute(Runnable r, Throwable t) { }
     //线程池终止时的钩子方法(停止钩子)
     protected void terminated() { }

  (1)beforeExecute:异步任务执行之前的钩子方法线程池工作线程在异步执行目标实例(如Runnable实例)前调用此钩子方法。此方法仍然由执行任务的工作线程调用。默认实现不执行任何操作,但可以在子类中对其进行自定义。此方法由执行目标实例的工作线程调用,可用于重新初始化ThreadLocal线程本地变量实例、更新日志记录、开始计时统计、更新上下文变量等。

(2)afterExecute:异步任务执行之后的钩子方法线程池工作线程在异步执行目标实例后调用此钩子方法。此方法仍然由执行任务的工作线程调用。此钩子方法的默认实现不执行任何操作,可以在调度器子类中对其进行自定义。此方法由执行目标实例的工作线程调用,可用于清除ThreadLocal线程本地变量、更新日志记录、收集统计信息、更新上下文变量等。

(3)terminated:线程池终止时的钩子方法terminated钩子方法在Executor终止时调用,默认实现不执行任何操作。

package com.bpm.example.demo.multiThread;

import org.junit.Test;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CreateThreadPoolDemo {
//线程本地变量,用于记录线程异步任务开始执行时间
private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
@Test
public void testHooks() throws InterruptedException {

ExecutorService pool = new ThreadPoolExecutor(2,4,60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(2))

{
//继承:调度器终止钩子
@Override
protected void terminated()
{
System.out.println("调度器已经终止!");
}

//继承:执行前钩子
@Override
protected void beforeExecute(Thread t, Runnable target)
{
System.out.println( target +"前钩被执行");
//记录开始执行时间
START_TIME.set(System.currentTimeMillis());
super.beforeExecute(t, target);
}

//继承:执行后钩子
@Override
protected void afterExecute(Runnable target, Throwable t)
{
super.afterExecute(target, t);
//计算执行时长
long time = (System.currentTimeMillis() - START_TIME.get()) ;
System.out.println( target + " 后钩被执行, 任务执行时长(ms):" + time);
//清空本地变量
START_TIME.remove();
}
};


for (int i = 0; i<=5;i++){
pool.execute(new Runnable() {
@Override
public void run() {
AtomicInteger threadNo = new AtomicInteger(1);
System.out.println("线程名:---"+threadNo);
threadNo.incrementAndGet();
}
});
}
Thread.sleep(20000);
pool.shutdown();
}
}