版权声明:本文为博主原创文章 http://blog.csdn.net/su20145104009 https://blog.csdn.net/su20145104009/article/details/86137015
模版方法:在抽象类中定义了一个模版方法,在模版方法中使用了一些该抽象类中定义的空方法,而这些空方法可以供子类实现。
我们在查看源码时经常能够看到在执行一些重要的方法时,往往调用了一些看似没有什么意义的空方法。其实这就是模版方法。
abstract class ThreadHolder {
/**
* 模版方法
* @param runnable
*/
public final void run(Runnable runnable) {
Objects.requireNonNull(runnable, "runnable required not null");
beforeRun();
runnable.run();
afterRun();
}
/**
* 在线程执行之前执行
*/
protected void beforeRun() {
}
/**
* 在线程执行完之后执行
*/
protected void afterRun() {
}
}
在抽象类ThreadHolder
中我们定义了beforeRun
和afterRun
两个空方法,供子类实现。然后在模版方法run
,我们在线程执行开始和结束分别调用beforeRun
和afterRun
。我们不关心beforeRun
和afterRun
做了什么,供子类按需实现。
然后定义一个实现类。
/**
* 子类,实现ThreadHolder的空方法
*/
class SimpleThread extends ThreadHolder {
@Override
protected void beforeRun() {
System.out.println("执行之前。。。");
}
@Override
protected void afterRun() {
System.out.println("执行之后。。。");
}
}
进行测试
public class AppTest {
public static void main(String[] args) {
SimpleThread simpleThread = new SimpleThread();
simpleThread.run(() -> {
int n = 10;
for (int i = 0; i < n; i++) {
System.out.println("current num is :" + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
输出结果:
执行之前。。。
current num is :0
current num is :1
current num is :2
current num is :3
current num is :4
current num is :5
current num is :6
current num is :7
current num is :8
current num is :9
执行之后。。。
其实模版方法被大量使用在各种源码中,通过使用者实现所需的方法,来达到某些监控/日志等目的。
比如在线程池ThreadPoolExecutor
中执行任务的方法
//模版方法
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
//执行之前
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
//执行结束
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
在执行任务之前之后调用了beforeExecute
和afterExecute
方法,源码中两个方法都是空的,供子类实现
protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }
所以在我们使用线程池时,如果需要在任务执行之前或者之后做一些监控/日志/计时等操作,通过继承ThreadPoolExecutor
类来重写beforeExecute
和afterExecute
方法实现。