线程无法停止

时间:2017-01-17 14:09:43

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

        @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的任何数字)时,线程无法停止?请帮我解决这个问题...感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

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

    runP rp = new Threadz().new runP();
    if (rp.num == 1) {
        rp.stop();
    }

它与0一起使用,因为int的默认值为0。 但是在应用程序的所有执行中并不一定如此,因为runP的线程可以在检查之前运行并增加numif (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;
        }
    }
}

答案 1 :(得分:0)

我确定你是否多次运行该程序,当程序实际停止时会出现这种情况。

原因是当你运行程序时,执行

的可能性要大得多
if(rp.num == 1) {rp.stop();}
num++方法run()之前的

更改值。

但是,您可能会遇到一种情况,即run方法中的循环在main方法中的if语句之前执行。

确保这种情况发生的一种方法是不断检查条件:

e.g。

public static void main(String[] a) {
   runP rp = new Threadz().new runP();

   while(true){
      if(rp.num == 1) {
         rp.stop(); 
         break;
      }
   }
}

答案 2 :(得分:0)

下面的语句是在线程开始执行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进行测试。

答案 3 :(得分:0)

检查public ActionResult GetData([DataSourceRequest]DataSourceRequest request) { IQueryable<CarModel> entity = getCars().ProjectTo<CarModel>(); var response = entity.ToDataSourceResult(request); return Json(response,JsonRequestBehavior.AllowGet); } 必须恰好发生在rp.num == 1正是一个点的位置,这是不太可能的。

rp.num方法中,启动一个每200毫秒递增main的线程。然后,检查是否num,但是当执行此代码时,取决于您无法真正控制的许多因素(操作系统的安排等等)。这可能是在10 ms之后(其中值为1),但也可能在300 ms之后(当值已经为2时)。当线程准确启动时也不确定。因此,您的线程也可能仅在测试后启动。您可以使用简单的打印语句num == 1替换支票if(rp.num == 1) {rp.stop()};,轻松地对此进行测试。如果你在打印之前再等一段时间,你可能会对我正在谈论的内容有更好的感受。

假设你想要从外面阻止可运行,我建议使用像Observer pattern这样的东西:

System.out.println(rp.num)

并且您的主要方法看起来像

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

}