什么线程睡眠方法中断?

时间:2017-03-23 11:00:03

标签: java multithreading

在阅读了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());
    }

4 个答案:

答案 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递归地通过新的RunnableEventQueue添加自身的异步调用,这似乎非常危险。

答案 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,然后睡眠主线程。