Java 线程无法停止

Java 线程无法停止,java,multithreading,Java,Multithreading,为什么我的线程不能停止 class Threadz { class runP implements Runnable { int num; private volatile boolean exit = false; Thread t; public runP() { t = new Thread(this, "T1"); t.start(); }

为什么我的线程不能停止

 class Threadz {

    class runP implements Runnable {
        int num;
        private volatile boolean exit = false;
        Thread t;
        public runP() {
            t = new Thread(this, "T1");
            t.start();
        }

        @Override
        public void run() {
            while(!exit) {
                System.out.println(t.currentThread().getName()+": "+num);
                num++;  
                try {
                    t.sleep(200);   
                } catch(InterruptedException e) {}
            }
        }
        public void stop() {
            exit = true;
        }
    }

    public static void main(String[] a) {
        runP rp = new Threadz().new runP();
        if(rp.num == 1) {rp.stop();}
    }

}

如果我使用rp.num==0,线程可以立即停止。但是,为什么当我更改rp.num==x(x是任何大于0的数字)时线程不能停止?请帮我解决这件事。。。感谢您的帮助。

因为此代码不是在线程的run()方法中执行的:

    runP rp = new Threadz().new runP();
    if (rp.num == 1) {
        rp.stop();
    }
它与0一起工作,因为int的默认值为0。 但这并不一定在应用程序的所有执行中都是正确的,因为
runP
的线程可以在检查之前运行并递增
num
if(rp.num==0)

在runP线程的run方法中移动停止条件:

@Override
public void run() {
    while(!exit) {
        System.out.println(t.currentThread().getName()+": "+num);
        num++;  
        try {
            t.sleep(200);   
        } catch(InterruptedException e) {}

        if (rp.num == 1) {
          exit = true;
        }
    }
}

我敢肯定,如果你多次运行这个程序,当程序真正停止运行时,就会出现这种情况

原因是在运行程序时,执行的机会要大得多

if(rp.num == 1) {rp.stop();}
run()
方法中的
num++
之前更改值

然而,您可能会偶然遇到这样一种情况,即在主方法中的if语句之前执行run方法中的循环

确保发生这种情况的一种方法是持续检查以下情况:

e、 g


在线程开始执行run方法之前执行下面的语句

if(rp.num == 1) {rp.stop();}
在上述语句之前添加Thread.sleep,它可以正常工作,因为它将在启动循环后执行此语句

  public static void main(String[] a) {
    runP rp = new Threadz().new runP();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
    if(rp.num > 1) {rp.stop();}
}

我已经将它设置为>1进行测试。

检查
rp.num==1
必须恰好发生在
rp.num
正好为1的点上,这是不太可能的

main
方法中,您启动一个线程,该线程每200毫秒递增
num
。之后,您将检查
num==1
,但此代码的确切执行时间取决于许多您无法真正控制的因素(操作系统的调度等)。这可能在10毫秒之后(值为1),但也可能在300毫秒之后(值已经为2)。另外,线程何时准确启动也不确定。因此,您的线程也可能仅在测试之后启动。通过替换check
if(rp.num==1){rp.stop()使用简单的打印语句
System.out.println(rp.num)
。如果您在打印之前再等待一段时间,您可能会更好地了解我所说的内容

假设您想阻止来自外部的runnable,我建议使用以下方法:

你的主要方法是

public static void main(String[] args) {
    MyListener l = new MyListener(1);
    Runnable r = new MyRunnable(l);
    new Thread(r).start();
}

我猜
runP rp=newthreadz().newrunp()正在创建和启动线程。但是,
如果(rp.num==1){rp.stop();}
恰好在该线程之后执行,则可能正好在另一个线程实际开始运行之前执行,因此
num
仍然为0。此外,线程可能已经运行多次,因此检查<代码> rpn==1 非常脆弱,并且可能更经常失败。请考虑使用<代码> RPNUM > 1 < /COD>而不是<代码> RPNU==1 < /COD>停止您的线程以确保您不会意外跳过停止条件。AtomicBoolean能够真正保持这种方法。此外,您需要在两个线程之间有一个完美的计时来命中==。你最好选择>好的。。我尽了最大努力,但最终还是做出了这个选择。。。谢谢brobtw如果我有两个线程,如何将var从一个线程传递到另一个线程?你能告诉我怎么做吗?不客气:)不需要传递变量,只需要在线程之间共享它。您可以使用在runP线程之间共享的AtomicInteger,并在runP的构造函数中提供AtomicInteger。应该很好,是的。我刚刚注意到,对于多线程处理,100次重复中有99次。所以我只是简单地将标签添加到搜索中,然后仔细决定是否有值得投票的答案;-)空缺已经结束,你又回来了。很高兴看到你回来:)那么放松了吗?谢谢这个标签:)我会检查你的。也许可以做点好生意:)
class MyRunnable implements Runnable {

    private final MyListener l;
    private volatile boolean exit;
    int num;

    public MyRunnable(MyListener l) {
        this.l = l;
        exit = false;
    }

    @Override
    public void run() {
        while(!exit) {
            System.out.println(t.currentThread().getName()+": "+num);
            l.check(num++);
            try {
                t.sleep(200);   
            } catch(InterruptedException e) {}
        }
    }

    public void stop() {
        exit = true;
    }
}

class MyListener {

    private final threshold;

    public MyListener(int x) {
        this.threshold = x;
    }

    public void check(MyRunnable r, int num) {
        if (num >= threshold)
            r.stop();
    }

}
public static void main(String[] args) {
    MyListener l = new MyListener(1);
    Runnable r = new MyRunnable(l);
    new Thread(r).start();
}