java线程问题,直接看代码吧。不好描述。

发布于 2022-09-01 12:13:26 字数 886 浏览 21 评论 0

Foo类实现了Runnable接口

public class Foo implements Runnable{
    private boolean isRun ;
    @Override
    public void run() {
        isRun = true;
        while (isRun){
            System.out.println("runing ......");
        }
    }
    public void stop(){
        this.isRun = false;
    }

    @Override
    public String toString() {
        return "Foo{" +
                "isRun=" + isRun +
                '}';
    }
}

测试类

public class ThreadTest {
    public static void main(String[] args) {
        Foo f = new Foo();
        Thread t = new Thread(f);
        t.start();
        f.stop();
        System.out.print(f);

    }

}

为什么执行了stop()方法之后,t线程没有停止执行呢。
我debug发现thread在运行start()方法之前,里面的Foo对象和执行stop()方法的Foo对象是同一个。按理说执行stop()方法后。f的isRun被设置成了false,线程读取到该变量变成false应该停止才对。
看thread的源码
求大神解答。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美人如玉 2022-09-08 12:13:27
  1. 因为你这是死循环
while (isRun){
            System.out.println("runing ......");
        }

而且isRun一直是true, 你应该改成:

@Override
public void run() {
    //isRun = true;
    while (isRun){
        System.out.println("runing ......");
    }
}

isRun一开始就初始化,应该这么写:

public class FooThread implements Runnable{
    private boolean isRun  = true;
    @Override
    public void run() {
        System.out.println("run begin...");
        //isRun = true;
        while (isRun){
            System.out.println("runing ......");
        }
    }
    public void stop(){
        System.out.println("call stop");
        this.isRun = false;
    }

    @Override
    public String toString() {
        return "Foo{" +
                "isRun=" + isRun +
                '}';
    }

    public static void main(String[] args) {
        FooThread f = new FooThread();
        Thread t = new Thread(f);
        t.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        f.stop();
        System.out.print(f);
    }
}

最终输出:

runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
runing ......
call stop
Foo{isRun=false}
猥琐帝 2022-09-08 12:13:27

这应该是一个老问题了. 我没做实验, 但按我的理解, private volatile boolean isRun; 可以解决你的问题.

这里涉及到一个java hotspot 过度优化的问题,

    isRun = true;
    while (isRun){
        System.out.println("runing ......");
    }

这里while(isRun){...} 会被JIT翻译为 本地代码. 因为没有volatile, 很大可能直接翻译为 while
(true){...}
. 有兴趣去 找一个java fastdebug 版本, 看看jit翻译后的汇编码, 这个我以前弄过.

至于@netingcn 同学的解决方案, 这里while不会成为热点代码, 所以不会做优化.

以上只是以前的一点经验, 也许不完全正确.

岁月无声 2022-09-08 12:13:26

t.start(); 并不是离开执行run方法,而是交给OS去调度。
针对你这个例子,执行的顺序是 f.stop() --> System.out.print(f) 也及时调用f对象的toString, 然后才开始线程执行。而在你的run方法中又设置 isRun = true; 所以线程无法停止。
修改Foo 如下:

public class Foo implements Runnable{
    private int isRun = 1;
    @Override
    public void run() {
       System.out.println("isRun Value : " + isRun);
        isRun = 0;

        while (isRun == 0){
            System.out.println("runing ......");
            try {
                Thread.sleep(1000l);
            } catch(Exception e) {

            }
        }
    }

    public void stop(){
        this.isRun = 2;
    }

    @Override
    public String toString() {
        return "Foo{" + "isRun=" + isRun + "}\n";
    }
}

这个时候你会看到类似这样的输出

Foo{isRun=2}
isRun Value : 2
runing ......
runing ......
runing ......
runing ......

说明 stop 确实在 run 之前先执行

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文