我一直在学习 Threads,是的……我是个菜鸟。我有一个问题,我不知道如何停止线程,因为 .spot() 方法已被弃用。我想知道如何安全地停止线程。我这样做了:
public class Principal{
private boolean bo1;
private Thread tr1;
public Principal(){
bo1 = true;
tr1 = new Thread(){
public void run(){
while(bo1){
//What the Thread does goes here, its a chronometer.
}
}
}; // The thread body stops here.
} // The constructor body stops here.
public void changeBo1(){
if(bo1 == true){
bo1 = false;
}
else{
bo1 = true;
}
} //Change bo1 ends here.
} //Class ends here.
所以我正在为自己制作一个迷你游戏,该方法的主体是一个计时表,显示我需要多长时间才能解决这个难题。交易是,当我开始一个新游戏时,我调用重置秒、分钟和小时值的方法以及 changeBo1() 所以时钟停止了。然后当我第一次点击屏幕时,计时开始。然后,当我改变游戏时。但是线程没有读取 boolean 值的变化,它重新启动到 0:00:00,并且在我不点击屏幕的情况下,继续到 0:00:01--- (这不会发生在第一个游戏中,因为变量是需要的,当我点击“新游戏”时,变量需要更改时会发生)。
如何让线程读取 boolean 值 bo1 的变化?
最佳答案
制作 bo1 volatile :
private volatile boolean bo1;
这是因为,有时一个线程可以在另一个线程更改该值后读取该值。对此的简单解释是每个线程都有自己的两个线程共享的内存副本,有时该私有(private)副本可能不同步。
bo1 是通常所说的哨兵变量。只是变量控制循环的一种奇特说法。
请记住,这两个线程不是同步的,因此它们可以处于任何状态。你必须小心地控制那个状态。仅仅因为您将 bo1
设置为 false 并不意味着使用它作为 sentinel 变量 的线程实际上已完成执行,因为它可能没有处理此更改并退出循环还没有。
您需要 join threads以确保执行完成。如果 Thread1 在 Thread2 上调用 join
,Thread1 将被阻塞,直到 Thread2 执行完毕。 (对自身调用 join
的线程不会被阻塞。)
这里是一个重写,使用上面提到的技术。
public class Principal{
private boolean bo1;
private Thread tr1;
public Principal(){
bo1 = true;
tr1 = new Thread(){
public void run(){
while(bo1){
//What the Thread does goes here, its a chronometer.
}
}
}; // The thread body stops here.
} // The constructor body stops here.
public void stopThread(){
changeBo1();
tr1.join();
}
public void changeBo1(){
bo1 = !bo1;
} //Change bo1 ends here.
} //Class ends here.
如果您遇到需要循环处理数据的情况(例如解析流式传输协议(protocol),或者只是处理一些项目列表),那么遵循这样的模式可能会很有用:
public class ProcessRunnable implements Runnable{
private final Queue<Item> queue = new LinkedList<Item>();
public void run(){
while(active){
synchronized(queue){
while(queue.size()>0){
Item item = queue.remove();
//process item
}
queue.wait();
}
}
}
public void add(Item item){
synchronized(queue){
this.queue.add(item);
this.queue.notifyAll();
}
}
}
这带来了 notify和 wait功能。在对象上调用 Wait
将阻塞一个线程,直到另一个线程在同一对象上调用 notify
或 notifyAll
。这可用于指示数据可用,或者更一般地说,一些值得注意的事件已经发生。这是必要的,因为不等待会导致线程尽可能快地运行,从而消耗大量 CPU。
关于java - 如何在 Java 中停止一个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17481315/