【发布时间】:2019-05-25 12:16:28
【问题描述】:
我有一个由一个线程修改并由另一个线程读取的 ArrayList。 阅读线程很乐意阅读修改后列表中剩余的任何内容。当从列表中删除所有项目时,它应该停止。 在 Collections.synchronizedList() 的 java doc 中提到,我们应该在对列表执行任何操作之前手动同步列表。
用户必须手动同步返回的 迭代时列出:
列表列表 = Collections.synchronizedList(new ArrayList()); ...同步(列表){ 迭代器 i = list.iterator(); // 必须在同步块中 而 (i.hasNext()) 富(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 阅读: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 移除: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(没有 synchronized 块)让它工作,但每当修改列表时,它似乎都会产生创建新列表的开销。 p>
在使用 sychronizedList 获得与 CopyOnWriteArrayList 相同的结果时,我是否遗漏了什么?
【问题讨论】:
-
一个线程从列表中删除项目,另一个线程继续阅读,直到它为空。这是基于现实生活场景吗?你想用这个设计解决什么问题?
-
似乎生产者-消费者,如果是这样,那么也许列表不是你想要使用的
-
也许你想使用阻塞队列,
BlockingQueue<String> blockingQueue = new LinkedBlockingDeque<>(); -
我正在尝试它。但是假设一个游戏角色的背包里有 30 个金币。当他花费这些时,同样应该反映在记分板上。
-
现在看来背包物品应该是一个 bound 属性,允许监听器收到状态更改通知,例如使用属性更改监听器。
标签: java multithreading synchronized java-threads