2013-02-21 56 views
2

我通常看到两种方法来实现一个守护进程,它会执行一些工作并进入睡眠状态并再次唤醒。哪种方法更好的遵循以下两种方法来安排和停止线程

  1. while(flag)的方法,其中flag为true,如果我们想停止守护进程,则被其他类设置为false。

    while(flag){ 
        //do something 
        Thread.sleep(10000l); 
    } 
    
  2. 使用固定延迟调度ScheduledThreadPoolExecutor。

国际海事组织,第二种方法是更清洁和易于测试。有人可以比较这两种方法。可以先解决任何内存问题?

谢谢

回答

2

方法2)被推荐。

方法之一不是由基础线程系统(尤其是在UNIX上)强大的随机觉醒,你也需要实现自己的错误处理

方法有两个可以让你从底层的Thread和工作与RunnableCallable

而且方法1)具有时钟漂移的问题,即你的任务需要一个非零时间,因此执行将执行每十秒钟。 ScheduledExecutorService实际上会每秒执行一次执行,或者如果需要,每十秒钟执行一次执行。

方法2)提供了一种简单的方法来安排线程在一段时间内执行某些操作,并按照javadoc中的示例将其杀死。

最后,ExecutorSevice更容易关闭自定义线程,只需调用executorService.shutdown()然后executorService.awaitTermination()即可等待最后一个任务完成。

您可能需要注意的一件事是javadoc中的这个gem - “如果任务的任何执行遇到异常,则后续执行被取消”。这意味着要么你必须非常小心你的Callabletry/catch或者你需要这样子类ScheduledExecutorService(从javadoc中获取):

public class MyScheduledExecutor extends ScheduledThreadPoolExecutor { 

    public MyScheduledExecutor(int corePoolSize) { 
     super(corePoolSize); 
    } 

    @Override 
    protected void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     if (t == null && r instanceof Future<?>) { 
      try { 
       Object result = ((Future<?>) r).get(); 
      } catch (CancellationException ce) { 
       t = ce; 
      } catch (ExecutionException ee) { 
       t = ee.getCause(); 
      } catch (InterruptedException ie) { 
       Thread.currentThread().interrupt(); // ignore/reset 
      } 
     } 
     if (t != null) { 
      System.out.println(t); 
     } 
    } 
} 
+0

+1好点。除了最后一段不适用,因为OP对固定延迟而不是固定费率的调度方案感兴趣。 – 2013-02-21 10:09:17

3

可以先接近造成任何内存问题?

不是。最大的问题是管理flag变量的可见性。每当我看到有人提出这种方法时,我立即就投下它。由于某种原因,Thread类封装了中断标志的概念。