2011-09-08 84 views
2

我有一个守护程序线程,它在打开页面时启动。当页面关闭时,线程停止。所以,在我的课持有线程,我有这样的创建:如何停止运行多个实例的同一线程

class A { 
private static volatile boolean isStopped=false; 

//this method is called then the page is loaded 
public void testListener() { 
    Thread listener = new Thread(new Runnable() { 
     public void run() { 
     while(!isStopped) { 
     //perform listener event 
     try { 
     //after every event sleep for a while 
     Thread.sleep(1000 *2) 
     } catch(InterruptedException e){} 
     } 
    } 
    }); 
} 
listener.setName("Test-Server-Daemon"); 
listener.setDaemon(true); 
listener.start(); 

// reset back to false so thread can be restarted when the page load event, 
// call this method instance 
if (isStopped) { 
    isStopped=false; 
} 
} 

/**This is called when page is closed**/ 
public static void stopListener() { 
    isStopped=true; 
    } 
} 

经过调查,我注意到,当页面内关闭,而不是再次打开说30秒的间隔,线程正常停止。

但是,当页面关闭并在2秒钟的时间间隔内重新打开时,旧线程不会停止,因此会与新线程同时运行。

所以你可以从下面看到图片,当我关闭并快速打开页面时,我再次启动了相同的线程。

有谁知道如何防止这种情况发生?

我已经尝试使用线程interrupt在哪里我重置互斥锁,但没有喜悦。

编辑:

isStopped是volatile

enter image description here

+0

尝试呼叫'了Thread.interrupt()'方法。 – Salw

+0

我已经尝试过了 - 在我的问题中也提到了它。 – Bitmap

+0

'执行监听事件'是做什么的?它是否以某种方式检查事件对象的存在?如果是这样,使用wait/notify会不会更高效? –

回答

2

从@Jordão酒店的回答遵循,isStopped变量应该是每个线程。我会建议使用像一个AtomicBoolean和改变你的线程代码约为:

public AtomicBoolean testListener() { 
    final AtomicBoolean isStopped = new AtomicBoolean(false); 
    Thread listener = new Thread(new Runnable() { 
     public void run() { 
      while(!isStopped.get()) { 
       ... 
      } 
     } 
    }); 
    listener.setName("Test-Server-Daemon"); 
    listener.setDaemon(true); 
    listener.start(); 
    return isStopped; 
} 

然后回到你的页面控制器,你可以这样做:

AtomicBoolean isStopped = testListener(); 
// do the page stuff 
... 
// when done stop the thread 
isStopped.set(true); 
0

尝试使isStopped volatile,即private static volatile boolean isStopped=false;。这两个线程(主要和你自己)之间的内存同步可能存在滞后。

+0

'@Bart van Heukelom' isStopped已经不稳定,请参阅编辑。 – Bitmap

2

您可能会覆盖isStopped的值false之前旧线程有机会看到它应该停止。问题就在这里:

if(isStopped) 
{ 
    isStopped=false; 
} 

你应该更好地隔离代码:为每个线程创建的A单独的实例,使isStopped一个实例volatile场(不static)。并删除该代码块...

1

如果您的标志isStopped不是真的至少2秒,您的线程可能会在这种情况发生时睡觉。一个更简单的解决方案是避免启动/停止线程,因为这可能会造成尽可能多的开销,因为它可以节省(这肯定会使问题复杂化)

这就是我要做的就是启动线程一次而且只启动一次。

public void run() { 
    try { 
    while(true) { 
     if(!isStopped) { 
     //perform listener event 
     } 
     //after every event sleep for a while 
     Thread.sleep(1000 *2); 
    } 
    } catch(InterruptedException e){} 
} 

通过设置标志,它停止执行,但线程继续检查。

1

尝试使用AtomicBoolean而不是布尔字段。 使用compareAndSet方法;让我知道如果你需要更多的澄清,因为javadoc是非常有用的。

0

将您的实例化移动到您的方法之外并使其变为静态。这个保证人的,你只会有这个线程的一个实例。

if(listener.isAlive()) try { Thread.sleep(100); } catch (InterruptedException ie) {} 

listener = new Thread(new Runnable() { 
    public void run() { 
      while(!isStopped) { 
       //perform listener event 
       try { 
        //after every event sleep for a while 
        Thread.sleep(1000 *2) 
       } 
       catch(InterruptedException e){} 
     } 
    } 
}); 

现在你不会,直到前一个已停止启动一个新的线程:

private static Thread listener; 

给你方法一旦做到这一点,你可以添加此。

(NB,如果没有把握的IsAlive()是正确的,则可能需要创建自己的线程中执行,以准确反映如果线程停止,如果它不是)

0

我会用一个java.util.concurrent.ScheduledExecutorService。它将管理线程和任务的调度。

例如:

import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledFuture; 
import java.util.concurrent.TimeUnit; 

public class Scheduler { 

static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 

static ScheduledFuture<?> future; 

// called when the page is opened 
public static void open() { 
    future = service.scheduleAtFixedRate(new Runnable() { 
     public void run() { 
      //perform listener event 
     } 
    }, 0, 2, TimeUnit.SECONDS); // every 2 seconds 


} 

// called when the page is closed 
public static void close() { 
    // stop listener event 
    future.cancel(true); 
    future = null; 
} 

}

+0

'@Laurent Legrand' - 我知道这一点,我决定按个人原因去做。 thankx – Bitmap

相关问题