Java:清空循环

我正在使用以这种方式执行的while循环创建一个程序:

  1. 主线程进入while循环。
  2. while循环中没有任何反应。
  3. 线程将保持while循环,直到满足条件。
  4. 另一个线程运行一个满足所述条件的函数。

这是一个例子:

while(path != null); 

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

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

码:

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

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

 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 。)

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

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

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

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

 CountDownLatch latch = new CountDownLatch(1); 

用以下内容替换你的while (path != null)

 latch.await(); 

在您的主要代码中,只需:

 path = somePath; latch.countDown(); 

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

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

2定义路径变量为volatile:

  volatile String path;