Как избежать синхронизированных блоков в коде Java - PullRequest
0 голосов
/ 15 января 2019

Я работаю над простым компонентом, где мой класс содержит ссылку на объект, который поддерживает операции добавления и функцию отправки.
После вызова функции отправки указанный объект необходимо заменить новым. Мой API поддерживает операции добавления, которые отправляют элемент, как только он достигнет определенного размера, НО в некоторых случаях мне нужно будет проверить, что элемент был отправлен независимо от его размера через некоторое время. Единственное решение, о котором я мог подумать, - это синхронизация всего класса, чего я хотел бы избежать. Есть мысли о других решениях / возможном рефакторинге, чтобы избежать синхронизации всего?

pulic class MyClass{
        private MyObject ref;
        private int maxObjectsToSubmit;

        public MyClass(int maxItems){ 
              this.maxObjectsToSubmit = maxItems;
        }

        public void add(Item obj){
              ref.add(obj);
              if(ref.size() == maxObjectsToSubmit){
                   submit();
              }else if(obj.isVeryImportant()){
                    SomeAPI.runThreadInExactDelayToCreateRaceCondition(new Runnable{ 
                     public void run(){
                          //Submit only if o is still waiting to be submittet.
                     // if ref does not contains obj than it has already been submitted
                         if(ref.contains(obj)){
                           submit()
                         }
                  })
             }
        }

           private void submit(){
                 SomeAPI.doSomething(ref);
                 this.ref = new MyObject();
            }
}

Состояние гонки:

  1. T1 добавляет некоторые предметы, пока не прибудет очень важный предмет, который начинается T2
  2. T1 достигает maxObjectsToSubmit, а ref.size () == maxObjectsToSubmit возвращает true
  3. T2 запускается, ref.contains (obj) возвращает true

Это может привести к тому, что пустой объект будет отправлен / Один и тот же объект будет отправлен дважды / etc '

1 Ответ

0 голосов
/ 15 января 2019

Я бы предложил создать новый экземпляр Myobject и вставить в него элемент obj, а затем вызвать submit, поскольку он имеет высокий приоритет, поэтому он не должен ждать, пока Myobject достигнет максимального предела.

public void add(Item obj) {
        if (obj.isVeryImportant()) {
            SomeAPI.runThreadInExactDelayToCreateRaceCondition(new Runnable {
                public void run () {
                    //Submit only if o is still waiting to be submittet.
                    // if ref does not contains obj than it has already been submitted
                    MyObject local = new MyObject();
                    local.add(obj);
                    local.submit();
                }
            });
        } else {
            ref.add(obj);
            if (ref.size() == maxObjectsToSubmit) {
                submit();
            } else if (obj.isVeryImportant()) {

            }
        }
    }
...