ScheduledFuture.cancel()方法

时间:2015-06-12 10:42:09

标签: java multithreading concurrency synchronized scheduledexecutorservice

Code below是来自"Programming Concurrency on the JVM: Mastering Synchronization, STM, and Actors" book

的示例

我不明白为什么作者同步 stopEnergySource 方法,它只是取消了由 replenishTask 变量代表的ScheduledFuture任务?没有其他方法可以使用此变量。 是否需要同步Future.cancel调用或者它只需要ScheduledFuture?

public class EnergySource {
  //...
  private static final ScheduledExecutorService replenishTimer =
    Executors.newScheduledThreadPool(10);
  private ScheduledFuture<?> replenishTask;

  private EnergySource() {}

  private void init() {   
    replenishTask = replenishTimer.scheduleAtFixedRate(new Runnable() {
      public void run() { replenish(); }
    }, 0, 1, TimeUnit.SECONDS);
  }

  public static EnergySource create() {
    final EnergySource energySource = new EnergySource();
    energySource.init();
    return energySource;
  }

  public long getUnitsAvailable() { 
    //...
  }

  public long getUsageCount() { 
    //...
  }

  public boolean useEnergy(final long units) {
    //...
  }

  public synchronized void stopEnergySource() { // what for **synchronized** is?
    replenishTask.cancel(false); 
  }

  private void replenish() { 
    //...
  }
} 

1 个答案:

答案 0 :(得分:0)

  

没有其他方法可以使用此变量。是否需要同步Future.cancel调用或者它只需要ScheduledFuture?

我相信代码的作者试图强制内存障碍,以防不同的线程试图首先调用stopEnergySource()启动作业。

但是,如果是这种情况,那么init()方法应该synchronized,因为他们没有安全发布replenishTask字段。该字段不是final,并且允许编译器返回create(...),但稍后继续构造和初始化EnergySource对象。

如果多个线程正在创建并停止这些对象,您可以轻松地在stopEnergySource(...)中获取NPE,即使其上包含synchronized关键字。