线程基础:为什么相同的代码在不同的类中产生不同的输出?

时间:2014-05-22 01:13:04

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

以下代码正常,即在我按Hello!之前打印enter。当我按下回车键时,它会停止。正如所料,这很好。

但是当我将相同的代码复制到另一个名为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();

    }

}

enter image description here

将代码复制到OneDateCached CLASS: -

enter image description here


编辑: -

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();

    }

}

3 个答案:

答案 0 :(得分:1)

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

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();
    }
}

答案 1 :(得分:1)

如果

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指的是static中声明的One字段。如果在类SomeOther中声明了相同的代码,那么它指的是static中声明的SomeOther字段。

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

答案 2 :(得分:1)

也许你在打电话

new One().stopThread();

而不是

new OneDataCached().stopThread();