Java中是否有并发列表';是JDK吗?
如何创建一个并发列表实例,在这个实例中我可以通过索引访问元素?JDK有我可以使用的类或工厂方法吗?因为获取位置和从给定位置获取元素的行为自然需要一些锁定(不能让列表在这两个操作之间进行结构更改) 并发集合的基本思想是,每个操作本身都是原子的,可以在没有显式锁定/同步的情况下完成Java中是否有并发列表';是JDK吗?,java,list,concurrency,Java,List,Concurrency,如何创建一个并发列表实例,在这个实例中我可以通过索引访问元素?JDK有我可以使用的类或工厂方法吗?因为获取位置和从给定位置获取元素的行为自然需要一些锁定(不能让列表在这两个操作之间进行结构更改) 并发集合的基本思想是,每个操作本身都是原子的,可以在没有显式锁定/同步的情况下完成 因此,从给定的列表中获取位于n位置的元素作为原子操作在预期并发访问的情况下没有太大意义。中存在并发列表实现。特别是。如果您只需要简单的调用同步,就可以很好地使用: List<Object> objList
因此,从给定的
列表
中获取位于n
位置的元素作为原子操作在预期并发访问的情况下没有太大意义。中存在并发列表实现。特别是。如果您只需要简单的调用同步,就可以很好地使用:
List<Object> objList = Collections.synchronizedList(new ArrayList<Object>());
List objList=Collections.synchronizedList(new ArrayList());
ConcurrentLinkedQueue
如果你不关心有索引的访问,只想保持一个列表的插入顺序保持特性,你可以考虑一个。由于它实现了Iterable,因此在添加完所有项后,可以使用增强的for语法循环内容:
Queue<String> globalQueue = new ConcurrentLinkedQueue<String>();
//Multiple threads can safely call globalQueue.add()...
for (String href : globalQueue) {
//do something with href
}
Queue globalQueue=new ConcurrentLinkedQueue();
//多个线程可以安全地调用globalQueue.add()。。。
for(字符串href:globalQueue){
//用href做点什么
}
CopyOnWriteArrayList是ArrayList的线程安全变体,其中
所有可变操作(添加、设置等)都由
创建基础数组的新副本
CopyOnWriteArrayList是同步列表实现列表接口及其java.util.concurrent包的一部分及其线程安全集合的并发替代方案
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
公共类CopyOnWriteArrayList
实现列表、随机访问、可克隆、java.io.Serializable
CopyOnWriteArrayList是故障安全的,当在迭代过程中修改基础CopyOnWriteArrayList时,不会引发ConcurrentModificationException。请使用ArrayList的单独副本
这通常成本太高,因为复制阵列涉及到每次更新操作,因此将创建一个克隆副本。CopyOnWriteArrayList是仅用于频繁读取操作的最佳选择
/**
* Returns a shallow copy of this list. (The elements themselves
* are not copied.)
*
* @return a clone of this list
*/
public Object clone() {
try {
@SuppressWarnings("unchecked")
CopyOnWriteArrayList<E> clone =
(CopyOnWriteArrayList<E>) super.clone();
clone.resetLock();
return clone;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
*返回此列表的浅表副本。(a)要素本身
*不复制。)
*
*@返回此列表的克隆
*/
公共对象克隆(){
试一试{
@抑制警告(“未选中”)
CopyOnWriteArrayList克隆=
(CopyOnWriteArrayList)super.clone();
clone.resetLock();
返回克隆;
}捕获(CloneNotSupportedException e){
//这不应该发生,因为我们是可克隆的
抛出新的InternalError();
}
}
:您可以包装任何Collections.synchronizedList()
实现(List
、ArrayList
或第三方列表)。使用LinkedList
可以保护对每个方法(读写)的访问。使用synchronized
或增强for循环时,必须手动同步整个迭代。在迭代时,其他线程甚至被完全阻止读取。您还可以分别为每个iterator()
和hasNext
调用进行同步,但是可以执行next
ConcurrentModificationException
- :修改成本很高,但请等待免费阅读。迭代器从不抛出
,它们在迭代器创建时返回列表的快照,即使列表在迭代时被另一个线程修改。对于不经常更新的列表很有用。更新时首选批量操作,如ConcurrentModificationException
——内部阵列的复制次数较少addAll
:非常类似于Vector
,但迭代也是同步的。但是,如果向量在迭代时被另一个线程修改,迭代器可以抛出synchronizedList(newarraylist())
ConcurrentModificationException
- 如果只在列表末尾添加/删除或迭代列表,则
或Queue
可能是另一种选择Deque
只允许在一端添加,从另一端删除,Queue
允许在两端添加和删除。无法通过索引进行访问。有多个实现具有比任何Deque
所能提供的更好的并发属性。查看中的“所有已知实现类”,那些在列表
包中的实现是并发的。您还可以看看,它包含专门针对单个消费者或单个生产者的更快的队列实现java.util.concurrent
:无需等待,线程安全,但不可修改集合。不可修改列表()
- &:另一个是Java9和更高版本
ConcurrentSkipListMap
代替ArrayList
,例如
NavigableMap<Integer, T> map = new ConcurrentSkipListMap<>();
您还可以通过调用map.put(index,item)
来修改“列表”(即映射)中任何项目的值
将项目放入映射或按索引检索它们的平均成本为O(log(n)),而ConcurrentSkipListMap
是无锁的,这使得它明显优于sayVector
(旧同步版本的ArrayList
)
您可以使用
// Add item to end of the "list":
map.put(map.size(), item);
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentSkipListMap;
public class ConcurrentAddOnlyList<V> implements List<V> {
private NavigableMap<Integer, V> map = new ConcurrentSkipListMap<>();
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public boolean contains(Object o) {
return map.values().contains(o);
}
@Override
public Iterator<V> iterator() {
return map.values().iterator();
}
@Override
public Object[] toArray() {
return map.values().toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return map.values().toArray(a);
}
@Override
public V get(int index) {
return map.get(index);
}
@Override
public boolean containsAll(Collection<?> c) {
return map.values().containsAll(c);
}
@Override
public int indexOf(Object o) {
for (Entry<Integer, V> ent : map.entrySet()) {
if (Objects.equals(ent.getValue(), o)) {
return ent.getKey();
}
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
for (Entry<Integer, V> ent : map.descendingMap().entrySet()) {
if (Objects.equals(ent.getValue(), o)) {
return ent.getKey();
}
}
return -1;
}
@Override
public ListIterator<V> listIterator(int index) {
return new ListIterator<V>() {
private int currIdx = 0;
@Override
public boolean hasNext() {
return currIdx < map.size();
}
@Override
public V next() {
if (currIdx >= map.size()) {
throw new IllegalArgumentException(
"next() called at end of list");
}
return map.get(currIdx++);
}
@Override
public boolean hasPrevious() {
return currIdx > 0;
}
@Override
public V previous() {
if (currIdx <= 0) {
throw new IllegalArgumentException(
"previous() called at beginning of list");
}
return map.get(--currIdx);
}
@Override
public int nextIndex() {
return currIdx + 1;
}
@Override
public int previousIndex() {
return currIdx - 1;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(V e) {
// Might change size of map if currIdx == map.size(),
// so need to synchronize
synchronized (map) {
map.put(currIdx, e);
}
}
@Override
public void add(V e) {
synchronized (map) {
// Insertion is not supported except at end of list
if (currIdx < map.size()) {
throw new UnsupportedOperationException();
}
map.put(currIdx++, e);
}
}
};
}
@Override
public ListIterator<V> listIterator() {
return listIterator(0);
}
@Override
public List<V> subList(int fromIndex, int toIndex) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean add(V e) {
synchronized (map) {
map.put(map.size(), e);
return true;
}
}
@Override
public boolean addAll(Collection<? extends V> c) {
synchronized (map) {
for (V val : c) {
add(val);
}
return true;
}
}
@Override
public V set(int index, V element) {
synchronized (map) {
if (index < 0 || index > map.size()) {
throw new IllegalArgumentException("Index out of range");
}
return map.put(index, element);
}
}
@Override
public void clear() {
synchronized (map) {
map.clear();
}
}
@Override
public synchronized void add(int index, V element) {
synchronized (map) {
if (index < map.size()) {
// Insertion is not supported except at end of list
throw new UnsupportedOperationException();
} else if (index < 0 || index > map.size()) {
throw new IllegalArgumentException("Index out of range");
}
// index == map.size()
add(element);
}
}
@Override
public synchronized boolean addAll(
int index, Collection<? extends V> c) {
synchronized (map) {
if (index < map.size()) {
// Insertion is not supported except at end of list
throw new UnsupportedOperationException();
} else if (index < 0 || index > map.size()) {
throw new IllegalArgumentException("Index out of range");
}
// index == map.size()
for (V val : c) {
add(val);
}
return true;
}
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public V remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
}
// Add item after last item in the "list":
map.put(map.isEmpty() ? 0 : map.lastKey() + 1, item);
// Add item before first item in the "list":
map.put(map.isEmpty() ? 0 : map.firstKey() - 1, item);
class MyClass {
List<MyType> myConcurrentList = new ArrayList<>();
void myMethod() {
synchronzied(myConcurrentList) {
doSomethingWithList;
}
}
}