今天发现一个问题,不解.
TaskStatistic类源码
/**
*
*/
package cn.tohot.webdown.statistic;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import cn.tohot.webdown.persist.StatisticDAO;
import cn.tohot.webdown.persist.TaskCountRecord;
import cn.tohot.webdown.util.Config;
/**
* 任务状态定时统计线程,只记录发生了变动的统计结果.<br>
* 以单例模式运行,通过观察者模式发送统计结果<br>
* 典型的观察者有客户端通讯和统计曲线图
*
* @author 杨
*
*/
public class TaskStatistic extends CommonStatisticSource {
static private int statisticRate = Config.getApplicationConfig().statisticRate();
static private TaskStatistic thread = null;
private static Logger log = Logger.getLogger(TaskStatistic.class);
private final ScheduledExecutorService schedule = Executors.newSingleThreadScheduledExecutor();
private boolean started = false;
private TaskStatistic() {
}
public static TaskStatistic getSingleScheduledThread() {
if (thread == null) {
thread = new TaskStatistic();
}
return thread;
}
/**
* 在垃圾收集前停止线程
* @see java.lang.Object#finalize()
*/
protected void finalize() throws Throwable {
this.stop();
super.finalize();
}
/**
* 启动,以固定的延迟频率统计数据库中任务的状态,如果状态发生变化则通知监听者,并记录.
*/
public void start() {
if (started)
return;
if (log.isInfoEnabled())
log.info("启动任务统计线程");
started = true;
final StatisticDAO dao = new StatisticDAO();
schedule.scheduleWithFixedDelay(
new Runnable() {
TaskCountRecord lastRecord = null;
public void run() {
TaskCountRecord totalCount = dao.countTaskStatus();
// 任务数没有变化则不更新
if (!totalCount.equals(lastRecord)) {
lastRecord = totalCount;
tellAllObservers(totalCount);
dao.save(totalCount);
}
notifyAll(totalCount);
}
},
statisticRate,
statisticRate,
TimeUnit.SECONDS
);
}
/**
* 结束
*/
public void stop() {
schedule.shutdown();
started = false;
if (log.isInfoEnabled())
log.info("停止任务统计线程");
}
}
CommonStatisticSource
/**
*
*/
package cn.tohot.webdown.statistic;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
/**
* 简单统计消息源
*
* @author 杨
*
*/
public class CommonStatisticSource implements StatisticSource {
private static Logger log = Logger.getLogger(CommonStatisticSource.class);
final protected List<StatisticObserver> observers = new ArrayList<StatisticObserver>();
/**
* 把消息通知所有观察者
* @param message
*/
final protected void tellAllObservers(Object message) {
for (StatisticObserver obs : observers) {
if (obs != null) {
try {
obs.tellMe(message);
} catch (Exception e) {
log.error("监听器更新出错", e);
}
}
}
}
public void notifyAll(Object me){
//do
}
/*
* (non-Javadoc)
*
* @see
* cn.tohot.webdown.statistic.StatisticMessageSource#addObserver(cn.tohot
* .webdown.statistic.StatisticObserverIface)
*/
public void addObserver(StatisticObserver observer) {
observers.add(observer);
if(log.isDebugEnabled()) log.debug("增加一个观察者");
}
/*
* (non-Javadoc)
*
* @see
* cn.tohot.webdown.statistic.StatisticMessageSource#removeObserver(cn.tohot
* .webdown.statistic.StatisticObserverIface)
*/
public void removeObserver(StatisticObserver observer) {
observers.remove(observer);
if(log.isDebugEnabled()) log.debug("删除一个观察者");
}
}
后来我把notifyAll改成了tellAllObsever,发现是可以调用的.
但为什么notifyAll就不行呢?
这个Object的final方法有什么特殊约束吗?
经过一段时间思考,
应该是混淆了inner class的notifyAll()和outer class的notifyAll(),
可以把代码"notifyAll(totalCount); "改写成 " TaskStatistic.this.notifyAll(totalCount); ".
用明确的this引用来声明方法所属对象 ,果然不再报错了!