-1

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

  1. 我开始这样的线程:counter.start();counter线程在哪里。
  2. 当我想停止线程时,我会这样做:counter.interrupt()
  3. 在我的线程中,我会定期进行此检查:Thread.interrupted(). 如果它从线程中给出trueI return,因此它会停止。

如果需要,这里有一些细节:

如果您需要更多详细信息,它们就在这里。从 invent 调度线程我以这种方式启动一个计数器线程:

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();
            }
        });
    }
};

PS我没有看到“你好!!!!!!!!!!!!!” 在终端...

4

5 回答 5

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.sleep、 or Object.wait、 or Lock.lockInterruptibly,会检查标志,如果设置了,则InterruptedException在清除标志后会抛出一个。

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

有两种检查标志的方法:

  1. interrupted()
  2. isInterrupted()

第一个清除中断标志;第二个没有。您必须决定哪个版本对您的应用程序逻辑“更正确”。

于 2010-03-21T18:27:27.367 回答
1

查看JavaSpecialists时事通讯中的这篇文章,其中介绍了如何interrupt()正确地线程化和管理它。

于 2010-03-21T18:32:23.707 回答
0

是的,这是要走的路

于 2010-03-21T18:25:38.960 回答
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

于 2010-03-21T18:27:03.660 回答
0
  1. 为此目的,使用单独的 volatile 变量 (boolean isStopped)被认为是一种更好的方法 ( link )。

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

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

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

另一种方法是isInterrupted()方法。

于 2010-03-21T18:29:19.973 回答