集册 Java零基础学习教程 使用Concurrent集合

使用Concurrent集合

黑派客     最近更新时间:2020-01-16 05:30:08

586

我们在前面已经通过ReentrantLockCondition实现了一个BlockingQueue

public class TaskQueue {
    private final Lock lock = new ReentrantLock();    private final Condition condition = lock.newCondition();    private Queue<String> queue = new LinkedList<>();    public void addTask(String s) {
        lock.lock();        try {
            queue.add(s);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }    public String getTask() {
        lock.lock();        try {            while (queue.isEmpty()) {
                condition.await();
            }            return queue.remove();
        } finally {
            lock.unlock();
        }
    }
}

BlockingQueue的意思就是说,当一个线程调用这个TaskQueuegetTask()方法时,该方法内部可能会让线程变成等待状态,直到队列条件满足不为空,线程被唤醒后,getTask()方法才会返回。

因为BlockingQueue非常有用,所以我们不必自己编写,可以直接使用Java标准库的java.util.concurrent包提供的线程安全的集合:ArrayBlockingQueue

除了BlockingQueue外,针对ListMapSetDeque等,java.util.concurrent包也提供了对应的并发集合类。我们归纳一下:

interfacenon-thread-safethread-safe
ListArrayListCopyOnWriteArrayList
MapHashMapConcurrentHashMap
SetHashSet / TreeSetCopyOnWriteArraySet
QueueArrayDeque / LinkedListArrayBlockingQueue / LinkedBlockingQueue
DequeArrayDeque / LinkedListLinkedBlockingDeque

使用这些并发集合与使用非线程安全的集合类完全相同。我们以ConcurrentHashMap为例:

Map<String, String> map = ConcurrentHashMap<>();
// 在不同的线程读写:
map.put("A", "1");
map.put("B", "2");
map.get("A", "1");

因为所有的同步和加锁的逻辑都在集合内部实现,对外部调用者来说,只需要正常按接口引用,其他代码和原来的非线程安全代码完全一样。即当我们需要多线程访问时,把:

Map<String, String> map = HashMap<>();
展开阅读全文