i'm trying to stop a specific Thread
that implement Runnable
.
I already try a few things that i found while googling it, but still can't find the best answer.
I have two Class
.
1st is Timer
. This class will create a countdown. It will send a result if countdown == 0
to another class.
public class Timer implements Runnable {
public Timer(int countdown, Room room, String cmdName) {
this.room = room;
this.countdown = countdown;
this.cmdName = cmdName;
}
public void setResultThread(IResultThread resultThread) {
this.resultThread = resultThread;
}
@Override
public void run() {
for (int i = countdown; i >= 0; i--) {
countdown--;
if (i == 0) {
resultThread.setResult(true);
}
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2nd is User
. I want to stop the Thread
from this class.
Thread thread;
String threadName = "player-" + user.getName();
thread = utils.getThreadByName(threadName);
if (thread != null) {
thread.stop(); // i used stop before, but i read its not a good way
thread.interrupt();
}
if (nextTurn == 4) {
// do something
} else {
int countDown = 10
//getting player name
if (playerName != null) {
String newThreadName = "player-" + playerName;
Timer timer = new Timer(countDown, room, Send.PLAYER_TIMER.toString());
thread = new Thread(timer, newThreadName);
timer.setResultThread(resultThread);
thread.start();
}
}
I'm not sure if there's something wrong with my code or something.
I tried catch the exception, but the Thread
countdown is still running. Its seems like its interrupt while the Thread
is sleep. I ever tried with volatile boolean, but I don't think is a good way to approach in this case and of course its not working either.
I used thread.stop()
before, but its not a good idea. This is the 1st time I'm using Thread
, and its still a little bit confused for me.
I will appreciate any suggestion and answer. Thanks alot.
I put an answer just in case there's someone have a same problem with me.
@Override
public void run() {
try {
while (countdown >= 0) {
TimeUnit.MILLISECONDS.sleep(1000);
countdown--;
if (countdown == 0) {
resultThread.setResult(true);
}
}
} catch (InterruptedException e) {
countdown = 0;
Thread.currentThread().interrupt();
//e.printStackTrace();
}
}
答案 0 :(得分:0)
The preferred way, IMO, to stop your Timer is to have eg. a cancel method
public class Timer implements Runnable {
...
public void cancel() {
countdown = 0;
}
...
}
Then replace thread.stop()
with timer.cancel()
, obviously you would need a reference to timer
or have Timer
extend Thread
instead of implementing Runnable
.
And as Andy said, in your run()
method it should be
run() {
...
try {
for () {
...
}
} catch (...
}
答案 1 :(得分:0)
无需拨打Thread.stop()
。
当你中断线程时你的代码当前没有停止的原因是在循环中发生了中断的处理:
for (int i = countdown; i >= 0; i--) {
// ...
try {
// Sleep
} catch (InterruptedException e) {
}
}
当线程在睡眠期间(或之前)被中断时,中断被吞下":你处理它,所以循环只会继续到下一次迭代,如果有的话。
罗宾威廉姆斯有一个关于英国警察的短剧,由于缺乏枪支,他们不得不说'停止!或者......我会说再次停止!"。如果你一直调用中断,最终你的线程会完成,因为最终循环会执行适当的次数。但这会非常麻烦,而且非常不必要。颠倒循环和try / catch的顺序:
try {
for (int i = countdown; i >= 0; i--) {
// ...
// Sleep
}
} catch (InterruptedException e) {
}
现在,当中断发生时,执行将移至循环之后,因此不再发生循环迭代。
(当然,您可以保留代码原样,只需return
中的catch
;但多个返回点可能会使代码难以推理)
当你赶上InterruptedException
:
// ...
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
这会在当前线程上设置中断标志(令人困惑的是,这与InterruptedException
正交),允许任何调用Runnable
的代码知道线程被中断。
执行此操作并非严格:如果您知道代码位于线程调用堆栈的顶部(如此处:没有&# 34;呼叫者"意识到中断)。但重新打断线程几乎总是做正确的事情(*),在这种情况下根本不会受到伤害。
(*)你不会重新抛出InterruptedException
,或者如果你正在编写线程框架代码,并且你肯定知道这是不正确的事情的例子。
答案 2 :(得分:0)
从另一个类停止线程的正确方法是中断正在运行的线程。然后在线程中,您必须检测中断,然后结束线程执行。
不要调用thread.stop,也不需要使用volatile变量
例如
公共类StoppingThreadFromOtherClassExample {
public static void main(String[] args) throws InterruptedException {
StoppingThreadFromOtherClassExample stoppingThreadFromOtherClassExample = new StoppingThreadFromOtherClassExample();
stoppingThreadFromOtherClassExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
Thread myThread = new Thread(new MyClassA());
myThread.start();
Thread.sleep(1000);
myThread.interrupt();
myThread.join();
}
}
class MyClassA implements Runnable {
int counter = 0;
@Override
public void run() {
while (true) {
counter++;
System.out.println(counter);
if (Thread.interrupted()) {
System.out.println("this thread was interrupted. it will stop now!!");
break;
}
}
}
}
答案 3 :(得分:-2)
你可以为每个线程命名,每当你想要关闭线程时,只需遍历集合,查找线程的确切名称并调用stop。
获取正在运行的线程列表
得到一个可迭代的集合:
设置threadSet = Thread.getAllStackTraces()。keySet();