什么是使用while循环轮询的建议替代方法

时间:2011-12-01 00:09:40

标签: java swing

因此,这是我的代码,可以轮询我的应用模型中的更改。

    Thread refreshThread = new Thread(new Runnable() {

        public void run() {

            while(true)
            {                       
                if(TasksManager.isDirty())
                {
                    TasksManager.refreshTasks(true);
                    panel.repaint();
                }
            }
        }
    });
    refreshThread.start();  

现在它是一个巨大的CPU猪。 这是发生的事情的细分。

  1. TaskManager意识到已添加新内容。
  2. TaskManager将自己标记为脏。
  3. 当我的刷新线程发现它变脏时,它立即在模型和显示面板上执行刷新。
  4. 在RefreshTasks()结束时,模型再次标记为干净。
  5. 我不希望TaskManager启动刷新,因为它没有对查看面板的任何引用。

    我的一个想法是使用condition.await()。 TaskManager可以在标记为脏的情况下发出信号。但我看到锁和条件齐头并进。如果在函数开头没有获取Lock就可以使用Condition吗?

2 个答案:

答案 0 :(得分:4)

为什么不使用听众?

如果你有一个名为ContentChangedListener的TasksManager的简单子类。然后,您可以在一个侦听器中声明panel.repaint()内容,该侦听器向TasksManager注册,无论谁感兴趣。许多听众都可以根据需要注册。

在将TasksManager标记为脏的代码的位置,将其替换为循环以通知所有侦听器发生更改。

此解决方案的优点是不需要其他线程或循环。

答案 1 :(得分:4)

您可以使用wait()notifyAll()来避免高CPU使用率:

private final Object dirtyLock = new Object();

Thread refreshThread = new Thread(new Runnable() {
    public void run() {
       while(true){
           synchronized(dirtyLock){
               dirtyLock.wait(); // Send this thread to sleep until dirtyLock is unlocked                       
           }
           TasksManager.refreshTasks(true);
           panel.repaint();
        }
    });
refreshThread.start(); 

// When your TaskManager becomes dirty, do the following
public void changeToDirty(){
    TaskManager.setDirty(true);
    synchronized(dirtyLock){
           dirtyLock.notifyAll(); 
           // this will release the refresh thread which will repaint and then go to sleep
     }
}