Java:清空循环

时间:2011-12-07 02:16:02

标签: java multithreading

我正在制作一个带有以这种方式执行的while循环的程序:

  1. 主线程进入while循环。
  2. while循环中没有任何事情发生。
  3. 线程将保持while循环,直到满足条件。
  4. 另一个线程运行一个满足上述条件的函数。
  5. 以下是一个例子:

    while(path != null);
    

    类中还有另一个函数将路径设置为null,一旦发生这种情况,主线程就应该退出这个循环。另一个函数在另一个线程中调用。

    但是,即使path设置为null,主线程也不会退出循环。有什么建议吗?

    CODE:

    try 
     { 
      for (Node n:realpath) 
        { 
          Thread.sleep(100); 
          actor.walk(n); 
         }
        Thread.sleep(100); 
     } 
     catch (InterruptedException ex) 
      { 
        Logger.getLogger(VNScreen.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      realpath.clear(); 
      path = null;
    
    if(path == null)
        System.out.println("NULLED PATH");
    

4 个答案:

答案 0 :(得分:12)

忙碌的等待非常昂贵。我这样做:

Object LOCK = new Object(); // just something to lock on

synchronized (LOCK) {
    while (path != null) {
        try { LOCK.wait(); }
        catch (InterruptedException e) {
            // treat interrupt as exit request
            break;
        }
    }
}

然后,当您将path设置为null时,只需调用

即可
synchronized (LOCK) {
    LOCK.notifyAll();
}

(如果两段代码都在同一个对象中,您可以在this上同步。)

答案 1 :(得分:4)

您可能需要将path声明为volatile。如果变量未声明为volatile,则编译器可以自由地将其值缓存在寄存器中,因此无法识别对值的任何更改。

但总的来说这种代码风格很糟糕(除了一些低级实模式的东西)。当你的while循环正在循环时,它消耗了100%的CPU,所以无论其他什么过程来改变path的值都可能永远不会得到循环执行,而其他进程可以做一些平凡的事情,比如维护通信链接或更新鼠标光标位置也不会执行。

最好是进行某种基于事件/消息/信号量的通信,以便您的“循环”在继续之前等待信号。 “可接受”是利用某种延迟,例如Thread.sleep,这样你只需每隔几毫秒“轮询”一次变量。你也可以尝试Thread.yield,但这是一种废话,不会在一系列环境中产生可靠的结果。

答案 2 :(得分:1)

您可以使用CountDownLatch,而不是使用低级等待/通知方法,并避免忙于等待使用volatile。因为只有一个事件可以预期,所以将锁存器实例化为:

CountDownLatch latch = new CountDownLatch(1);

将您的while (path != null)替换为:

latch.await();

在您的主要代码中,只需执行以下操作:

path = somePath;
latch.countDown();

答案 3 :(得分:-1)

主线程没有退出循环,因为在while条件下没有任何东西,并且检查条件正在非常快速而且没有意义变化变量。你有2种方法可以解决这个问题: 1-in while循环等待短时间,例如5ms

    while(path != null){
     try{
       Thread.currentThread().sleep(50);
     }catch(){
       //do nothing
     }
    }

2 - 将路径变量定义为volatile:

  volatile String path;