【问题标题】:Threads basics: Why is the same code producing different output in different classes?线程基础:为什么相同的代码在不同的类中产生不同的输出?
【发布时间】:2014-07-10 20:53:19
【问题描述】:

以下代码可以正常工作,即在我按下enter 之前,它会打印Hello!。当我按下回车时,它停止了。这很好,正如预期的那样。

但是当我将 相同的代码 复制到另一个名为 OneDataCached 的类中时(所以它只是不同的类的名称)它不能按预期工作。它宁可打印Hello!,当我按下enter 时,它错过了一行,然后再次开始打印hello!

我对为什么会发生这种情况感到困惑,任何提示或指针将不胜感激。

public class One {
    static volatile boolean bool=true; 

    void stopThread(){
        bool=false;
    }

    public static void main(String [] args){

        new Thread(new Runnable() {
            public void run(){
                while(bool){
                    System.out.println("Hello!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        System.out.println("Press Return to stop ...");

        new Scanner(System.in).nextLine();
        new One().stopThread();

    }

}

将代码复制到 OneDateCached 类后:-


编辑:-

public class OneDataCached {
    static volatile boolean bool=true; 

    void stopThread(){
        OneDataCached.bool=false;
    }

    public static void main(String [] args){

        new Thread(new Runnable() {
            public void run(){
                while(OneDataCached.bool){
                    System.out.println("Hello!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        System.out.println("Press Return to stop ...");

        new Scanner(System.in).nextLine();
        new One().stopThread();

    }

}

【问题讨论】:

  • 您使用的是OneDataCached.bool 还是One.boolstatic 这种方式很有趣
  • @MadProgrammer 只是为了检查一下,我在while 循环的条件以及stopThread() 中将bool 更改为OneDataCached.bool;但这并没有帮助。尽管当我考虑到您的观点时,它是非常合法的。我编辑了问题。
  • 检查前两个答案,你改错了bool的状态
  • @SotiriosDelimanolis 我刚试过。没有帮助
  • 执行new OneDataCached().stopThread() 以获得您想要的行为。现在,您仍在检查OneDataCached.bool,但正在修改One.bool

标签: java multithreading thread-safety java.util.scanner volatile


【解决方案1】:

也许你在打电话

new One().stopThread();

而不是

new OneDataCached().stopThread();

【讨论】:

  • 非常感谢。我复制时忘记更改它。这有效。
【解决方案2】:

假设你已经逐字复制了代码,那么两个版本都会调用

new One().stopThread();

这意味着OneDataCached.bool 中的内容永远不会改变。 static不是你的朋友,一不留神就会出各种问题……

一种解决方案可能是创建一个自包含的专用Runnable...

public class Message implements Runnable {

    private volatile boolean bool = true;

    void stopThread() {
        bool = false;
    }

    @Override
    public void run() {
        while (bool) {
            System.out.println("Hello!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

然后只与您想要停止/修改的实例进行交互,例如...

public class TestMessage {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Message message = new Message();
        Thread t = new Thread(message);
        t.start();

        System.out.println("Press Return to stop ...");

        new Scanner(System.in).nextLine();
        message.stopThread();
    }
}

【讨论】:

  • 非常感谢您的解决方案。它澄清了我的概念。
【解决方案3】:

如果

new Thread(new Runnable() {
        public void run(){
            while(bool){
                System.out.println("Hello!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();

One 中声明,名称bool 是指在One 中声明的static 字段。如果在类SomeOther中声明了相同的代码,那么它是指在SomeOther中声明的static字段。

但是,new One().stopThread(); 将始终修改在 One 中声明的字段,您的线程不会查看这些字段。

【讨论】:

    猜你喜欢
    • 2022-12-05
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2012-09-01
    相关资源
    最近更新 更多