Нужно ли использовать синхронизацию Java на поле, которое может быть изменено одним планировщиком потока? - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть класс (внешний класс) со следующим

  1. a Поле списка для хранения данных

  2. метод получения для поля списка

  3. метод getDataFromDB для возврата списка из онлайновой базы данных

  4. внутренний класс, который реализует Runnable и изменяет поле List в своем методе run

  5. в методе initialize внешнего класса будет настроен SingleThreadScheduledExecutor, который запланирует запуск внутреннего класса

Мне интересно, нужно ли ставить блок синхронизации, где

  1. Поле списка читается в методе получения (2)

  2. поле List изменяется в методе run внутреннего класса (который является Runnable и будет запланирован SingleThreadScheduledExecutor) (4)

public class OutterClass{

  private List<Data> data;
  private ScheduledExecutorService scheduledExecutorService;

  @PostConstruct
  private void initialize(){
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    scheduledExecutorService.scheduleWithFixedDelay(new InnerClass(), // other configs);
  }

  private List<Data> getDataFromOnlineDB() {/* some work */}

  public synchronized List<Data> getData() { return data; }

  private class InnerClass implements Runnable {
    @Override
    public void run() {
      synchronized (OutterClass.this) {
        data = getDataFromOnlineDB();
      }
    }
  }
}

1 Ответ

0 голосов
/ 24 апреля 2019

Чтобы ответить на ваш вопрос, нам нужно знать предполагаемый шаблон доступа к управляемым данным.

Как написано, ваш код обрабатывает шаблон доступа, где управляемые данные назначаются в некоторый момент времени после создания объекта, и где к управляемым данным можно получить доступ в любой момент времени после создания объекта, где присваивание происходит в одном потоке, а доступ происходит из других потоков. Это тот шаблон доступа, который вы намереваетесь поддерживать?

Вот небольшое обновление, помогающее прояснить код. Единственными отличиями являются синтаксические перестановки. Функция точно такая же.

Главное обновление, на которое следует обратить внимание, заключается в том, что присвоение «данным» производится в установщике. Это делает синхронизацию немного более понятной.

public class OuterClass {

  // Some data to be managed.  Centralize all explicit references.
  private List<Data> data;
  public synchronized List<Data> getData() { return data; }
  public synchronized void setData(List<Data> data) { this.data = data; }

  // An executor used to launch code which asynchronously
  // compute and assigns the managed data.
  private ScheduledExecutorService scheduledExecutorService;

  // Tie into this instance lifecycle by launching
  // a thread that computes and assigns managed data.
  @PostConstruct
  private void initialize(){
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    scheduledExecutorService.scheduleWithFixedDelay(new InnerClass(), // other configs);
  }

  // Code which computes the data ...
  private List<Data> getDataFromOnlineDB() {/* some work */}

  // A runnable used to asynchronously compute and assign the managed data.
  private class InnerClass implements Runnable {
    @Override
    public void run() {
        setData( getDataFromOnlineDB() );
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...