在阅读了Java doc plus stackoverflow的答案之后没有这个问题,我想到Thread.sleep()
睡了当前的线程。好的。我如何确定我的当前线程是什么?
当此代码第一次运行时,它在一个执行main函数的默认线程中运行。我对吗?所以我们暂停这个线程一秒钟,以允许其他线程完成他们的工作。
在调用invokeLater()
之后,我们开始从全新线程运行render方法,所以当我们第二次调用Thread.sleep()
时,我们会中断这个新线程,而默认线程在没有任何线程的情况下运行有点中断。我在这里错过了什么吗?
我不明白的是,当我测试这段代码时,通过调用Thread.sleep()
它会中断整个Swing的事情:GUI,事件等。这意味着我的程序中没有与Swing相关的所有内容应该绝对无缝地运行,但似乎不是。
private void render() {
if (bs == null) {
createBufferStrategy(3);
bs = getBufferStrategy();
}
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
onRender(g);
g.dispose();
bs.show();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
EventQueue.invokeLater(() -> render());
}
答案 0 :(得分:1)
Thread.sleep()
睡眠当前线程[但]我如何确定当前线程是什么?
你误解了“当前线程”的含义。它表示调用方法的线程。
不要认为Thread.sleep(n)
对线程做任何事情。可以把它想象成一个 nothing 的方法,然后在几毫秒后返回n
。
当我将runnable传递给invokeLater时,我正在创建另一个线程并使用其方法run来调用该render方法。怎么可能?
invokeLater(r)
将r
放入队列。它还会创建EDT,但前提是EDT尚不存在。因此,永远不会有多个EDT。 EDT最终会从队列中选择r
并致电r.run()
。
在您的情况下,r
由lambda表达式() -> render()
创建。每次运行render()
功能时,它都会排队新的Runnable()
,EDT几乎会立即再次呼叫render()
。
当我测试这段代码时,通过调用Thread.sleep()它会中断整个Swing的东西
所有事件由EDT处理。当EDT调用你的render()
方法时,它不会做任何其他事情---它无法处理任何事件---直到render()
返回。 sleep(1000)
电话会确保render()
不会返回至少一整秒。这是一整秒,在此期间您的程序将无法响应任何用户输入。
由于EDT将或多或少地连续调用render()
功能,这意味着EDT几乎所有时间都在休眠,因此您的程序对用户输入的反应基本无响应。
答案 1 :(得分:0)
静态调用Thread.sleep ...
使当前正在执行的线程暂停(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。该线程不会失去任何监视器的所有权。
(由我强调的粗体陈述)。
如果你在一个似乎呈现某些UI的线程中调用它(或者通常在主运行线程中),你几乎肯定会看到可用性有所降低。
请注意,线程休眠和中断线程的概念是不同的。
这就是为什么你需要在调用InterruptedException
时捕获Thread.sleep
,因为线程可能在睡眠时被中断,例如另一个线程在睡眠线程上调用interrupt
。
另请注意,线程也可以中断本身,但显然不会在它同时睡眠时发生。
另请注意,在您的情况下render
递归地通过新的Runnable
向EventQueue
添加自身的异步调用,这似乎非常危险。
答案 2 :(得分:0)
我最不明白的是,当我测试这段代码时,通过调用Thread.sleep()它会中断整个Swing的事情:GUI,事件等。这意味着我的程序中没有与Swing相关的所有内容应该绝对无缝地运行,但似乎不是。
Swing中的所有UI事件都在一个线程中运行。通常它是一个主线程。如果这个线程用于某些活动,那么整个UI将挂起一段时间。为避免挂起,请勿在UI控件的侦听器中进行大量计算。
答案 3 :(得分:0)
只有Swing主线程或event dispatch thread才会执行渲染方法。
如果您希望该工作线程执行代码,则必须从主线程tell them explicitly开始。
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
@Override
public ImageIcon[] doInBackground() {
final ImageIcon[] innerImgs = new ImageIcon[nimgs];
for (int i = 0; i < nimgs; i++) {
innerImgs[i] = loadImage(i+1);
}
return innerImgs;
}
@Override
public void done() {
//Remove the "Loading images" label.
animator.removeAll();
loopslot = -1;
try {
imgs = get();
} catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
例如,您可以跨越几个SwingWorker,然后睡眠主线程。