【问题标题】:repaint() in Thread is making a high usage CPUThread 中的 repaint() 占用了高 CPU
【发布时间】:2015-10-25 16:58:15
【问题描述】:

我正在使用线程在我的应用程序中滚动文本:

public void run() {
    super.run();
    while (!isInterrupted()) {

        if (X >= -getPreferredSize().getWidth()) {
            X -= 2;
        } else {

            decrementMessagesInList(getMessages());
            addMessage(getMessages());

            prepare();
            X = getParentWidth();
        }
        try {
            Thread.sleep(50);

        } catch (InterruptedException e) {
            e.printStackTrace();
            break;
        }
        repaint();
    }
}

但是,看到睡眠时我的 CPU 使用率非常高,我需要减少它。谁能建议怎么做?

【问题讨论】:

  • 您告诉组件每 50 毫秒重绘一次。如果您不希望 CPU 使用率那么高,那么 1) 不要每 50 毫秒重新绘制一次,2) 改进您的绘制逻辑以使其更高效。查看Marquee Panel,它会滚动文本以查看 CPU 使用率是否更好。

标签: java multithreading swing


【解决方案1】:

如果我可以假设您的代码只需要滚动文本以响应某些事件(例如单击或拖动等),那么您应该让您的线程进入等待状态,然后让代码触发更新将通知发布到线程,然后该线程将唤醒并进行更新。像这样的:

Object syncObj = new Object();

public void run() {
    while (true) {
        try {
            syncObj.wait();
            if (X >= -getPreferredSize().getWidth()) {
                X -= 2;
            } else {
                decrementMessagesInList(getMessages());
                addMessage(getMessages());

                prepare();
                X = getParentWidth();
            }

            repaint();
        } catch (InterruptedException ie) {
            // handle the exception
        }
    }
}

然后在处理/生成导致需要滚动的事件的代码中

public void onClick(..)  {
   syncObj.notifyAll();
}

您还需要防范线程的虚假唤醒,以确保您等待的事件确实发生了。见Do spurious wakeups actually happen?

【讨论】:

  • 为了清楚起见,我从 ArrayList(从已解析的 XML)中获取文本。文本必须一直滚动,代码不能响应事件。
  • 你的意思是滚动到底部吗?您只需要在数组列表中的数据发生变化时运行该代码。
猜你喜欢
  • 2018-02-07
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2016-03-22
相关资源
最近更新 更多