从ThreadPoolExecutor重写的用于日志记录的函数 //代码实际上完全取自java并发 公共类TimingReadPool扩展ThreadPoolExecutor{ 私人最终线程本地开始时间 =新的ThreadLocal(); 私有最终记录器log=Logger.getLogger(“计时读取池”); private final AtomicLong numTasks=新的AtomicLong(); 私有最终AtomicLong totalTime=新的AtomicLong(); 执行前受保护的void(线程t,可运行r){ 超级执行前(t,r); log.fine(String.format(“线程%s:start%s”,t,r)); startTime.set(System.nanoTime()); } 执行后受保护的无效(可运行的r、可丢弃的t){ 试一试{ long-endTime=System.nanoTime(); long taskTime=endTime-startTime.get(); numTasks.incrementAndGet(); totalTime.addAndGet(任务时间); log.fine(String.format(“线程%s:结束%s,时间=%dns”), t、 r,任务时间); }最后{ super.afterExecute(r,t); } } 受保护的无效终止(){ 试一试{ log.info(String.format(“终止:平均时间=%dns”), totalTime.get()/numTasks.get()); }最后{ super.terminated(); } } }
是所有工作线程共享的从ThreadPoolExecutor重写的用于日志记录的函数 //代码实际上完全取自java并发 公共类TimingReadPool扩展ThreadPoolExecutor{ 私人最终线程本地开始时间 =新的ThreadLocal(); 私有最终记录器log=Logger.getLogger(“计时读取池”); private final AtomicLong numTasks=新的AtomicLong(); 私有最终AtomicLong totalTime=新的AtomicLong(); 执行前受保护的void(线程t,可运行r){ 超级执行前(t,r); log.fine(String.format(“线程%s:start%s”,t,r)); startTime.set(System.nanoTime()); } 执行后受保护的无效(可运行的r、可丢弃的t){ 试一试{ long-endTime=System.nanoTime(); long taskTime=endTime-startTime.get(); numTasks.incrementAndGet(); totalTime.addAndGet(任务时间); log.fine(String.format(“线程%s:结束%s,时间=%dns”), t、 r,任务时间); }最后{ super.afterExecute(r,t); } } 受保护的无效终止(){ 试一试{ log.info(String.format(“终止:平均时间=%dns”), totalTime.get()/numTasks.get()); }最后{ super.terminated(); } } },java,concurrency,Java,Concurrency,是所有工作线程共享的ThreadPoolExecutor实例。如果是,则不应同步执行前(…)和执行后(…)方法?如果答案是否定的,那么原因是“局部变量在线程堆栈中分配,状态变量如numtask、totalTime、startTime是线程限制/原子的” 您不需要在执行前和执行后同步,因为这两个方法中使用的所有字段都是线程安全的java.util.logging.Logger(来自API-Logger上的所有方法都是多线程安全的)或ThreadLocal和AtocmicLong,它们是专为免锁使用
ThreadPoolExecutor
实例。如果是,则不应同步执行前(…)和执行后(…)方法?如果答案是否定的,那么原因是“局部变量在线程堆栈中分配,状态变量如numtask、totalTime、startTime是线程限制/原子的” 您不需要在执行前和执行后同步,因为这两个方法中使用的所有字段都是线程安全的java.util.logging.Logger(来自API-Logger上的所有方法都是多线程安全的)或ThreadLocal和AtocmicLong,它们是专为免锁使用而设计的
至于局部变量,它们只能由一个线程访问,不需要任何同步。这些方法中的局部变量(endTime、taskTime)不需要被设置为原子变量,因为它在线程堆栈中分配,因此线程受限,因此不需要原子变量。我说的对吗?请回答第一部分“ThreadPoolExecutor实例是否由所有工作线程共享?”这是正确的。这是因为局部变量位于线程堆栈上,并且仅在该线程和唯一线程中可见。同步是指两个或多个线程共享相同的资源,例如“ThreadPoolExecutor实例是否共享…”我更愿意说“Worker是ThreadPoolExecutor的内部类,因此所有Worker都可以访问ThreadPoolExecutor成员/字段”我还要提到,terminated is只起作用,因为在调用过程中不会再次调用afterExecute。否则,需要更多的代码来确保平均计算结果与totalTime和numTasks的值一致。
// code exactly taken from java concurrency in practice
public class TimingThreadPool extends ThreadPoolExecutor {
private final ThreadLocal<Long> startTime
= new ThreadLocal<Long>();
private final Logger log = Logger.getLogger("TimingThreadPool");
private final AtomicLong numTasks = new AtomicLong();
private final AtomicLong totalTime = new AtomicLong();
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
log.fine(String.format("Thread %s: start %s", t, r));
startTime.set(System.nanoTime());
}
protected void afterExecute(Runnable r, Throwable t) {
try {
long endTime = System.nanoTime();
long taskTime = endTime - startTime.get();
numTasks.incrementAndGet();
totalTime.addAndGet(taskTime);
log.fine(String.format("Thread %s: end %s, time=%dns",
t, r, taskTime));
} finally {
super.afterExecute(r, t);
}
}
protected void terminated() {
try {
log.info(String.format("Terminated: avg time=%dns",
totalTime.get() / numTasks.get()));
} finally {
super.terminated();
}
}
}