我想创建一个类,该类定期运行某些内容(可运行),但是在需要时可以唤醒。如果我可以封装全部内容,则希望公开以下方法:

public class SomeService implements Runnable {


  public run() {
    // the code to run at every interval
  }

  public static void start() { }
  public static void wakeup() { }
  public static void shutdown() { }

}


不知何故,我已经走了这么远。但是我不确定这是否正确。

public class SomeService implements Runnable {

  private static SomeService service;
  private static Thread thread;
  static {
    start();
  }

  private boolean running = true;

  private SomeService() {
  }

  public void run() {
    while (running) {
      try {
        // do what needs to be done
        // perhaps peeking at a blocking queue
        // or checking for records in a database
        // trying to be independent of the communication
        System.out.println("what needs to be done");
        // wait for 15 seconds or until notify
        synchronized (thread) {
          try {
            thread.wait(15000);
          } catch (InterruptedException e) {
            System.out.println("interrupted");
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  private static void start() {
    System.out.println("start");
    service = new SomeService();
    thread = new Thread(service);
    thread.setDaemon(true);
    thread.start();
  }

  public static void wakeup() {
    synchronized (thread) {
      thread.notify();
    }
  }

  public static void shutdown() {
    synchronized (thread) {
      service.running = false;
      thread.interrupt();
      try {
        thread.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("shutdown");
  }

  public static void main(String[] args) throws IOException {

    SomeService.wakeup();
    System.in.read();
    SomeService.wakeup();
    System.in.read();
    SomeService.shutdown();

  }

}


我担心变量应声明为volatile。并且还担心我应该为“ thread.isInterrupted()”签入“需要完成的部分”。这看起来像是正确的方法吗?我应该将此翻译为执行人吗?如何强制执行预定的执行程序?

编辑

在对执行者进行试验之后,这种方法似乎是合理的。你怎么看?

public class SomeExecutorService implements Runnable {

  private static final SomeExecutorService runner
    = new SomeExecutorService();

  private static final ScheduledExecutorService executor
    = Executors.newSingleThreadScheduledExecutor();

  // properties

  ScheduledFuture<?> scheduled = null;

  // constructors

  private SomeExecutorService() {
  }

  // methods

  public void schedule(int seconds) {
    scheduled = executor.schedule(runner, seconds, TimeUnit.SECONDS);
  }

  public void force() {
    if (scheduled.cancel(false)) {
      schedule(0);
    }
  }

  public void run() {
    try {
      _logger.trace("doing what is needed");
    } catch (Exception e) {
      _logger.error("unexpected exception", e);
    } finally {
      schedule(DELAY_SECONDS);
    }
  }

  // static methods

  public static void initialize() {
    runner.schedule(0);
  }

  public static void wakeup() {
    runner.force();
  }

  public static void destroy() {
    executor.shutdownNow();
  }

}

最佳答案

对于初学者-您可能不想自己实现Runnable。你应该带一个Runnable。仅当希望将类传递给其他人执行时,才应实现Runnable。

为什么不只包装ScheduledExecutorService?这是一个快速(非常差,但应该可以正常运行)的实现。

public class PokeableService {

  private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
  private final Runnable codeToRun;

  public PokeableService (Runnable toRun, long delay, long interval, TimeUnit units) {
    codeToRun = toRun;
    service.scheduleAtFixedRate(toRun, delay, interval, units);
  }

  public void poke () {
    service.execute(codeToRun);
  }
}

07-28 01:22
查看更多