这是关闭线程的好方法吗?
我有一个简短的问题版本:
- 我启动了一个这样的线程:
counter.start();
,其中counter
是一个线程。 - 当我想停止线程时,我会这样做:
counter.interrupt()
- 在我的线程中,我定期执行此检查:
Thread.interrupted()
。如果它给出true
,我就会从线程返回
,结果,它会停止。
如果需要的话,这里有一些详细信息:
如果您需要更多详细信息,可以在这里找到。从发明调度线程中,我以这种方式启动一个计数器线程:
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 我没有看到“Hello!!!!!!!!!!!!”在航站楼...
I have a short version of the question:
- I start a thread like that:
counter.start();
, wherecounter
is a thread. - At the point when I want to stop the thread I do that:
counter.interrupt()
- In my thread I periodically do this check:
Thread.interrupted()
. If it givestrue
Ireturn
from the thread and, as a consequence, it stops.
And here are some details, if needed:
If you need more details, they are here. From the invent dispatch thread I start a counter thread in this way:
public static void start() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
where the thread is defined like that:
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();
}
});
}
};
The thread performs countdown in the "first" window (it shows home much time left). If time limit is over, the thread close the "first" window and generate a new one. I want to modify my thread in the following way:
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;
}
}
};
ADDED:
Because of some reasons it does not work. I have a method which interrupts the thread:
public static void partnerSelected() {
System.out.println("The button is pressed!!!!");
counter.interrupt();
}
This method is activated when a button is pressed. When I press the button I see the corresponding output in the terminal (so this method is activated and it does something). But because of some reasons it does not interrupt the thread. Here is the code for the thread:
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. I do not see "Hello!!!!!!!!!!!!!" in the terminal...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这被认为是使用单独的线程的更好方法(链接)挥发性变量(布尔 isStopped)用于此目的。
假设如果线程被中断,
interrupted()
方法将值从 true 更改为 false,即:System.out.println(Thread.interrupted()); //true
System.out.println(Thread.interrupted()); //错误的
另一种方法是
isInterrupted()
方法。It's considered a better way (link) to use separate volatile variable (boolean isStopped) for this purpose.
Assume that
interrupted()
method changes value from true to false if your thread was interrupted, i.e.:System.out.println (Thread.interrupted()); //true
System.out.println (Thread.interrupted()); //false
The alternative is
isInterrupted()
method.查看 JavaSpecialists 时事通讯中的这篇文章,其中介绍了如何
中断( )
线程并正确管理它。Check out this article from the JavaSpecialists newsletter, which covers how to
interrupt()
threads and manage this properly.编辑/序言
我想编辑并指出我今天在这里学到了教训。正如我在下面两段中解释的那样,没有理由实现布尔值;中断机制为我做到了这一点。出于某种原因,我假设“中断”会使线程停止运行(我不知道我认为 isInterrupted() 做了什么!)。
所以,这是一个不该做什么的例子。继续使用你的中断技巧!
最初的答案
我倾向于避免中断,但特别是停止线程。在您的情况下,您尝试使用interrupt()作为stop()的替代品,stop()已出于充分的理由被弃用。您需要做的就是声明一个布尔值,它表示线程是否应该停止计数,并让线程不断检查该布尔值。然后,当父线程准备好计数器停止时,它应该将布尔值设置为 true(停止),这将导致计数器线程在再次检查该值时立即停止。
在 Counter 线程的匿名类定义中,添加
public volatile boolean shouldStop;
。在run()
的开头,设置shouldStop = false;
。然后用shouldStop
替换所有Thread.interrupted()
(在if
语句中)。最后,不要调用counter.interrupt()
,而只需说counter.shouldStop = true;
。如果您想确保计数器在继续之前已停止,您还可以在设置shouldStop=true
后立即调用counter.join()
。Edit/Preamble
I'd like to edit and note that I've learned a lesson here today. There's no reason to implement a boolean as I explain in the following two paragraphs; the interrupt mechanism does that for me. For some reason I had assumed that "interrupt" stops the thread dead in its tracks (I don't know what I thought isInterrupted() did then!).
So, here is an example of what not to do. Keep on using your interrupt technique!
Original answer
I tend to avoid interrupt, but especially to stop a thread. In your case, you're trying to use interrupt() as an alternative to stop(), which has been deprecated for good reason. All you need to do is declare a boolean which represents whether the thread should stop counting, and have the thread continuously check that boolean value. Then, when the parent thread is ready for the counter to stop, it should set the boolean to true (stop), which will cause the counter thread to stop as soon as it checks the value again.
In your Counter thread's anonymous class definition, add
public volatile boolean shouldStop;
. At the beginning ofrun()
, setshouldStop = false;
. Then replace allThread.interrupted()
withshouldStop
(in yourif
statements). Finally, instead of callingcounter.interrupt()
, just saycounter.shouldStop = true;
. You can additionally callcounter.join()
right after settingshouldStop=true
if you want to ensure that counter has stopped before continuing.非常接近正确的想法。但是,在您的
catch (InterruptedException)
中,您应该:以便中断状态再次继续,并且不会执行第二个块中的操作。
编辑以使我的观点更清楚(因为OP的编辑似乎错过了我的最初观点:-P):你应该像这样编写你的代码:
第二次编辑来解释中断的作用。 :-)
当您调用
thread.interrupt()
时,该线程的中断标志就会被设置。该标志本身不会执行任何操作;这只是一个变量。这样做的原因是因为中断支持所谓的“协作线程管理”,其中线程的运行代码决定中断时要做什么(而不是被迫当场退出)。JDK 中内置的一些函数,例如 Thread.sleep、Object.wait 或 Lock.lockInterruptically,将进行检查em> 标志,如果设置了该标志,则清除该标志后会抛出 InterruptedException。
因此,如果您正在调用这些函数之一,则无需手动检查中断标志。但如果您不这样做,例如,如果您正在进行密集处理而不是等待某些事情,那么您应该定期检查该标志。
有两种方法可以检查中断标志:
interrupted()
isInterrupted()
第一种清除中断标志;第二个没有。您必须决定哪个版本对于您的应用程序逻辑“更正确”。
Pretty close to the right idea. However, in your
catch (InterruptedException)
you should have:so that the interrupted status goes on again, and doesn't do the stuff in the second block.
Edit to make my point clearer (because the OP's edit seems to have missed my initial point :-P): you should write your code like this:
Second edit to explain what interruption does. :-)
When you call
thread.interrupt()
, that thread's interrupted flag is set. That flag doesn't do anything on its own; it's just a variable. The reason for this is because interruption supports something called "cooperative thread management", where the thread's running code decides what to do when interrupted (rather than being forced to quit on the spot).Some functions built into the JDK, like
Thread.sleep
, orObject.wait
, orLock.lockInterruptibly
, will check the flag, and if it's set, then it'll throw anInterruptedException
after clearing the flag.So, if you're calling one of those functions, you don't need to manually check the interrupted flag. But if you're not, e.g., if you're doing intensive processing instead of waiting for something, then you should periodically check the flag.
There are two ways to check the flag:
interrupted()
isInterrupted()
The first one clears the interrupted flag; the second one doesn't. You have to decide which version is "more correct" for your application logic.
是的,这是要走的路
Yes it is the way to go