У меня есть ArrayList, который изменяется одним потоком и читается другим.
Читающая ветка с удовольствием читает все, что осталось в списке после внесения изменений. Он должен остановиться, когда все элементы будут удалены из списка.
В java-документе Collections.synchronizedList () упоминается, что мы должны вручную синхронизировать список перед выполнением каких-либо операций с ним.
Обязательно, чтобы пользователь вручную синхронизировался на возвращенном
список при итерации по нему:
Список списка = Collections.synchronizedList (new ArrayList ());
... синхронизированный (список) {
Iterator i = list.iterator (); // Должен быть в синхронизированном блоке
while (i.hasNext ())
Foo (i.next ()); } Несоблюдение этого совета может привести к недетерминированному поведению.
но при синхронизации он продолжает чтение до конца данных, прежде чем дает возможность другому потоку изменить список. (Да, потому что список заблокирован).
package test.thread.concurrency.synchronizedlist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class Solution {
private List<String> list = Collections.synchronizedList(new ArrayList<String>());
//private List<String> list = new ArrayList<>();
// private CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
public Solution() {
for (int i = 0; i < 30; i++) {
list.add("Item_" + i);
}
}
private void removeItemsFromList() {
synchronized (list) {
System.out.println("Removing: " + list.remove(0));
}
}
private void readFromLIst() {
synchronized (list) {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println("READ: "+ it.next());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
final Solution issue = new Solution();
Thread t1 = new Thread(() -> {
issue.readFromLIst();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 30; i++) {
issue.removeItemsFromList();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
t1.start();
t1.join();
t2.join();
System.out.println("Final List: " + issue.list);
}
}
Удаление: Item_0 READ: Item_1 READ: Item_2 READ: Item_3 READ: Item_4
ЧИТАТЬ: Item_5 READ: Item_6 READ: Item_7 READ: Item_8 READ: Item_9 READ:
Item_10 READ: Item_11 READ: Item_12 READ: Item_13 READ: Item_14 READ:
Item_15 READ: Item_16 READ: Item_17 READ: Item_18 READ: Item_19 READ:
Item_20 READ: Item_21 READ: Item_22 READ: Item_23 READ: Item_24 READ:
Item_25 READ: Item_26 READ: Item_27 READ: Item_28 READ: Item_29
Удаление: Item_1 Удаление: Item_2 Удаление: Item_3 Удаление: Item_4
Удаление: Item_5 Удаление: Item_6 Удаление: Item_7 Удаление: Item_8
Удаление: Item_9 Удаление: Item_10 Удаление: Item_11 Удаление: Item_12
Удаление: Item_13 Удаление: Item_14 Удаление: Item_15 Удаление:
Item_16 Удаление: Item_17 Удаление: Item_18 Удаление: Item_19
Удаление: Item_20 Удаление: Item_21 Удаление: Item_22 Удаление:
Item_23 Удаление: Item_24 Удаление: Item_25 Удаление: Item_26
Удаление: Item_27 Удаление: Item_28 Удаление: Item_29 Окончательный список: []
Я получил его, используя CopyOnWriteArrayList (без синхронизированный блок ), но, похоже, возникают накладные расходы на создание нового списка при каждом изменении списка.
Я что-то упускаю при использовании sychronizedList для достижения того же результата, что и в CopyOnWriteArrayList?