使用标志控制java线程不起作用

bttbmeg0  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(294)

我想使用flag来控制线程并相应地退出。这是我的密码:

import java.io.*;
import java.lang.Thread;
import java.util.concurrent.atomic.AtomicBoolean;

public class ThreadFlagExample {

    private static final AtomicBoolean running0 = new AtomicBoolean(false);
    private static final AtomicBoolean running1 = new AtomicBoolean(false);

    public static void main(String[] args) throws Exception {

        running0.set(true);
        running1.set(true);

        Runnable task = () -> {
            try {
                String name = Thread.currentThread().getName();
                System.out.println("name = " +name + ", running0 = " +running0.get() + ", running1 = " +running1.get());
                if (name == "Thread-0" && running0.get()) {
                    while (true) {
                        System.out.println("Foo Thread-0");
                        Thread.sleep(1000);
                        System.out.println("Bar Thread-0");
                    }
                }
                if (name == "Thread-1" && running1.get()) {
                    while (true) {
                        System.out.println("Foo Thread-1");
                        Thread.sleep(1000);
                        System.out.println("Bar Thread-1");
                    }
                }
            }
            catch (InterruptedException e) {
                // e.printStackTrace();
                System.out.println(Thread.currentThread().getName() + " interrpted");
            }
        };

        // run in a separate thread
        Thread thread1 = new Thread(task);
        thread1.start();

        Thread thread2 = new Thread(task);
        thread2.start();

        Thread.sleep(5000);
        running0.set(false);
        Thread.sleep(10000);
        running1.set(false);
    }
}

当我运行程序时,它会显示以下输出:

bash-4.4$ java ThreadFlagExample
name = Thread-0, running0 = true, running1 = true
name = Thread-1, running0 = true, running1 = true
^C

我希望程序运行thread-0并显示消息5秒,thread-1显示消息10秒。但是,two if块中的代码似乎永远不会执行,程序就挂在那里。有人能指出什么不对吗?

9rbhqvlz

9rbhqvlz1#

我知道你想做什么。您希望启动两个线程,然后一个线程在5秒后停止,另一个线程在10秒后停止。一旦它们都停止了,程序就退出了。
你有两个问题。首先,你把字符串和 == ,它将检查两个字符串是否为完全相同的对象,而不是具有相同的值。这将永远是 false 在你的例子中,这解释了为什么你的代码什么都没做。
另一个问题是,一旦开始在每个线程中循环,就永远不会检查标志的值,因此阻止它们的尝试不会起作用。这是您的代码,解决了这两个问题,看起来很有效:

import java.io.*;
import java.lang.Thread;
import java.util.concurrent.atomic.AtomicBoolean;

public class Test {

    private static final AtomicBoolean running0 = new AtomicBoolean(false);
    private static final AtomicBoolean running1 = new AtomicBoolean(false);

    public static void main(String[] args) throws Exception {

        running0.set(true);
        running1.set(true);

        Runnable task = () -> {
            try {
                String name = Thread.currentThread().getName();
                System.out.println("name = " +name + ", running0 = " +running0.get() + ", running1 = " +running1.get());
                if (name.equals("Thread-0")) {
                    while (running0.get()) {
                        System.out.println("Foo Thread-0");
                        Thread.sleep(1000);
                        System.out.println("Bar Thread-0");
                    }
                }
                if (name.equals("Thread-1")) {
                    while (running1.get()) {
                        System.out.println("Foo Thread-1");
                        Thread.sleep(1000);
                        System.out.println("Bar Thread-1");
                    }
                }
            }
            catch (InterruptedException e) {
                // e.printStackTrace();
                System.out.println(Thread.currentThread().getName() + " interrpted");
            }
        };

        // run in a separate thread
        Thread thread1 = new Thread(task);
        thread1.start();

        Thread thread2 = new Thread(task);
        thread2.start();

        Thread.sleep(5000);
        running0.set(false);
        Thread.sleep(10000);
        running1.set(false);
    }
}

我建议你在创建时给你的线程明确的名字。依赖java为线程提供的名称总有一天会给您带来麻烦,因为不能保证这些名称在java的未来版本中不会改变。docs只声明:“如果在创建线程时未指定名称,则为其生成新名称”。

相关问题