java - 如何在 Java 中停止一个线程

标签 java multithreading

我一直在学习 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();
        }
    }
}

这带来了 notifywait功能。在对象上调用 Wait 将阻塞一个线程,直到另一个线程在同一对象上调用 notifynotifyAll。这可用于指示数据可用,或者更一般地说,一些值得注意的事件已经发生。这是必要的,因为不等待会导致线程尽可能快地运行,从而消耗大量 CPU。

关于java - 如何在 Java 中停止一个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17481315/

相关文章:

java - 如何在android中使用ViewFlipper从ImageURLs的ArrayList制作幻灯片?

java - java.io.FileNotFoundException:app/libs/perfectjpattern-core-1.0.0.jar(无此文件或目录)

java - 关联、组合和聚合 - 用 java 实现

c++ - 将帧保存到磁盘时防止丢帧

java - 用于阻塞队列的 notify() 而不是 notifyAll()

Java : Object escape by Iterator and innerclass

java - 如何从 SOAP 消息中删除空 header ?

java:如何解析类似html的xml

java - java中使用DTO对象时的线程安全

java - ConcurrentLinkedQueue代码解释