2011-12-09 43 views
1

我想制作一种方法,可以安全地停止循环中运行的线程,允许在将控制权返回到制动器之前完成最后一个循环。等待线程循环完成

现在,无论我尝试什么,我都会冻结。可能出于僵局或什么; Java并不是我惯常的环境,所以这可能是另一个等待/通知问题。

boolean isRunning = true; 

@Override 
public void run() { 
    super.run(); 

    while (isRunning) { 
     // Do work... 
    } 

    synchronized(this) { 
     this.notify(); 
    } 
} 

public void stopSafely() { 
    isRunning = false; 

    try { 
     synchronized(this) { 
      this.wait(); 
     } 
    } catch (InterruptedException ex) { 
     // Handle... 
    } 
} 

这种方法(除了事实上,我上同步this,但它例如简单起见)的问题是,如果notifywait之前调用,调用者将冻结。

我确定玩​​环绕的块可以解决问题,但我似乎无法得到正确的组合。

有什么想法?

回答

2

只是去真正简单的解决方案:

private volatile boolean isRunning = true; 

@Override 
public void run() { 
    while (isRunning) { 
     // Do work... 
    } 
} 

public void stopThread() { 
    isRunning = false; 
} 

这基本上是Thread.interrupted()内部做,所以你可以用这个也:

在这种情况下
@Override 
public void run() { 
    while (Thread.interrupted()) { 
     // Do work... 
    } 
} 

你必须调用interrupt()在线程上。

0

找到一个更简单的解决方案,这样的变化时,它只是从检查isRunning阻止:

boolean isRunning = true; 

@Override 
public void run() { 
    while (true) { 
     synchronized(this) { 
      if (!isRunning) break; 
     } 

     // Do work... 
    } 
} 

public void stopSafely() { 
    synchronized(this) { 
     isRunning = false; 
    } 
} 
+0

如果你保留这个,使用私有同步stopSafely(){isRunning = false;}这是更简单和等效。 – Snicolas

+0

但是,像你一样同步整个运行方法并不是一个好主意。 – Snicolas

+0

正如所写,这将阻止任何呼叫stopSafely,不是? –

1

我希望第二个方法是从不同的线程调用了一个与run方法。我敢打赌。

在这种情况下,将isRunning = false放入synchronized块中就足够了。只有一个线程可以进入在给定监视器上同步的块。

顺便说一下,不要调用super.run(),这是没用的,不是一个好的编程习惯。

0

首先让make isRunning变化。

volatile boolean isRunning = true; 

的问题是,Java运行时做一些优化和价值不是体现在其他线程,即使第一个线程改变的价值。