Как добавить объекты в список с потоком и одновременно использовать список, не получая исключение ConcurrentModificationException? - PullRequest
1 голос
/ 15 февраля 2020

Название говорит обо всем, у меня есть таймер t1, который периодически добавляет объекты в список. Затем у меня есть другой таймер t2, повторяющийся в списке с постоянными интервалами для отображения его содержимого.

Я полностью понимаю, почему я получаю эти исключения, но я не могу придумать правильный ответ, чтобы избежать этого. Iv'e пытался запустить мои операции в синхронизированном режиме (список) {} и тому подобное, но ничего не получается. Мой алгоритм, кажется, работает очень хорошо, несмотря на эти исключения, но я все же хотел бы сделать его чистым.

Любая идея?

Редактировать: я использую java .util.Timer;

Ответы [ 2 ]

2 голосов
/ 15 февраля 2020

Весь доступ к списку во многом оборачивается синхронизированным блоком, например так:

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public final class Answer {
    private static final int FIVE_SECONDS = 5 * 1000;
    private static final int TWO_SECONDS = 2 * 1000;

    public static void main(String... args) {
        // this list contains the values that the producer will add to and the consumer will pull from
        final List<Long> theList = new ArrayList<>();

        // consumes all values found in theList
        new Timer("consumer").scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                final List<Long> copy;
                synchronized (theList) {
                    // we make a copy and clear theArray as quickly as possible in 
                    // order to not block the producer for too long
                    copy = new ArrayList<>(theList);
                    theList.clear();
                }

                System.out.println("copy = " + copy);
            }
        }, 1, FIVE_SECONDS);

        // adds the current time in ms to theList every 2 seconds
        new Timer("producer").scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                synchronized (theList) {
                    theList.add(System.currentTimeMillis());
                }
            }
        }, 1, TWO_SECONDS);
    }
}

При этом использование BlockingQueue сделает это за вас.

1 голос
/ 15 февраля 2020

https://www.baeldung.com/java-mutex Возможно, взгляните на мьютекс-структуры, они могут пригодиться

...