这是关闭线程的好方法吗?

时间:2010-03-21 18:22:03

标签: java multithreading interrupt

我有一个问题的简短版本:

  1. 我开始这样一个帖子:counter.start();,其中counter是一个帖子。
  2. 当我想要停止线程时,我会这样做:counter.interrupt()
  3. 在我的帖子中,我会定期进行此项检查:Thread.interrupted()。如果它从线程中提供truereturn,那么它就会停止。

  4. 以下是一些细节,如果需要:

    如果您需要更多详细信息,请点击此处。从发明调度线程我以这种方式启动一个反线程:

    public static void start() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                showGUI();
                counter.start();
            }
        });
    }
    

    其中线程的定义如下:

    public static Thread counter = new Thread() {
        public void run() {
            for (int i=4; i>0; i=i-1) {
                updateGUI(i,label);
                try {Thread.sleep(1000);} catch(InterruptedException e) {};
            }
                // The time for the partner selection is over.
            SwingUtilities.invokeLater(new Runnable() {
                    public void run() {    
                    frame.remove(partnerSelectionPanel);
                    frame.add(selectionFinishedPanel);
                    frame.invalidate();
                    frame.validate();
                }
            });
        }
    };
    

    线程在“第一个”窗口中执行倒计时(它显示主页很长时间)。如果时间限制结束,则线程关闭“第一个”窗口并生成一个新窗口。我想用以下方式修改我的线程:

    public static Thread counter = new Thread() {
        public void run() {
            for (int i=4; i>0; i=i-1) {
                if (!Thread.interrupted()) {
                    updateGUI(i,label);
                } else {
                    return;
                }
                try {Thread.sleep(1000);} catch(InterruptedException e) {};
            }
            // The time for the partner selection is over.
            if (!Thread.interrupted()) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {    
                    frame.remove(partnerSelectionPanel);
                    frame.add(selectionFinishedPanel);
                    frame.invalidate();
                    frame.validate();
                }
            });
            } else {
                return;
            } 
        }
    };
    

    增加:

    由于某些原因,它不起作用。我有一个中断线程的方法:

    public static void partnerSelected() {
        System.out.println("The button is pressed!!!!");
        counter.interrupt();
    }
    

    按下按钮时激活此方法。当我按下按钮时,我在终端中看到相应的输出(所以这个方法被激活,它会做一些事情)。但由于某些原因,它不会中断线程。这是线程的代码:

    public static Thread counter = new Thread() {
        public void run() {
            for (int i=40; i>0; i=i-1) {
                    if (Thread.interrupted()) {
                        System.out.println("Helloo!!!!!!!!!!!!!!!");
                        return;
                    }
                updateGUI(i,label); 
                try {Thread.sleep(1000);} catch(InterruptedException e) {};
            }
                // The time for the partner selection is over.
                if (Thread.interrupted()) {
                    System.out.println("Helloo!!!!!!!!!!!!!!!");
                    return;
                }
            SwingUtilities.invokeLater(new Runnable() {
                    public void run() {    
                    frame.remove(partnerSelectionPanel);
                    frame.add(selectionFinishedPanel);
                    frame.invalidate();
                    frame.validate();
                }
            });
        }
    };
    

    P.S。我没有看到“你好!!!!!!!!!!!!!”在终端......

5 个答案:

答案 0 :(得分:5)

非常接近正确的想法。但是,在您的catch (InterruptedException)中,您应该:

Thread.currentThread().interrupt();

以便中断状态再次开启,并且不会在第二个块中执行操作。


编辑以使我的观点更清晰(因为OP的编辑似乎错过了我的初始点:-P):你应该像这样编写你的代码:

try {
    for (int = 40; i > 0; --i) {
        updateGUI(i, label);
        Thread.sleep(1000);
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();  // <-- THIS LINE IS IMPORTANT
}

第二次编辑以解释中断的作用。 : - )

当您致电thread.interrupt()时,该线程的中断标志已设置。那面旗帜本身没有做任何事情;它只是一个变量。这是因为中断支持称为“协作线程管理”的东西,其中线程的运行代码决定在中断时做什么(而不是被迫当场退出)。

JDK中内置的一些函数,如Thread.sleepObject.waitLock.lockInterruptibly,将检查标志,如果已设置,那么它清除标志后会抛出InterruptedException

因此,如果您正在调用其中一个函数,则无需手动检查中断的标志。但是,如果你不是,例如,如果你正在进行密集处理而不是等待某事,那么你应该定期检查标志。

有两种方法可以检查标志:

  1. interrupted()
  2. isInterrupted()
  3. 第一个清除中断的旗帜;第二个没有。您必须确定哪个版本对您的应用程序逻辑“更正确”。

答案 1 :(得分:1)

查看JavaSpecialists新闻简报中的这篇文章,其中介绍了如何interrupt()线程并正确管理。

答案 2 :(得分:0)

是的,这是要走的路

答案 3 :(得分:0)

我想编辑并注意到我今天在这里吸取了教训。正如我在以下两段中解释的那样,没有理由实现布尔值;中断机制为我做了这件事。出于某种原因,我曾假设“中断”使线程停止在其轨道上(我不知道我认为是什么isInterrupted()然后!)。

所以,这里有一个不做的例子。继续使用你的中断技术!

(请不要低估我...)


我倾向于避免中断,尤其是停止线程。在您的情况下,您尝试使用interrupt()作为stop()的替代方法,该方法已被弃用。您需要做的就是声明一个布尔值,它表示线程是否应该停止计数,并让线程连续检查该布尔值。然后,当父线程准备让计数器停止时,它应该将布尔值设置为true(停止),这将导致计数器线程在再次检查该值时立即停止。

在Counter线程的匿名类定义中,添加public volatile boolean shouldStop;。在run()开头,设置shouldStop = false;。然后将所有Thread.interrupted()替换为shouldStop(在if语句中)。最后,不要只是调用counter.interrupt(),而是说counter.shouldStop = true;。如果您想在继续之前确保计数器已停止,您可以在设置counter.join()后立即致电shouldStop=true

答案 4 :(得分:0)

  1. 为此目的,使用单独的volatile变量(boolean isStopped)被认为是一种更好的方式(link)。

  2. 如果您的线程被中断,假设interrupted()方法将值从true更改为false,即:

  3. System.out.println (Thread.interrupted()); //true

    System.out.println (Thread.interrupted()); //false

    替代方法是isInterrupted()方法。