Concurrent集合 Atomic类
生活随笔
收集整理的這篇文章主要介紹了
Concurrent集合 Atomic类
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Block Queue的意思就是說當(dāng)一個(gè)線程調(diào)用getTask方法的時(shí)候會(huì)讓線程進(jìn)入等待狀態(tài)直到條件滿足,線程被喚醒以后,getTask方法才會(huì)被返回
java.util.concurrent包里面就提供了線程安全的BlockQueue集合ArrayBlockQueue就已經(jīng)實(shí)現(xiàn)了線程安全的Block Queue
package com.leon.day05;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class TaskQueueDemo {public static void main(String[] args) throws InterruptedException {// 最后我們通過一個(gè)main方法創(chuàng)建一個(gè)TaskQueue// 我們不需要自己編寫一個(gè)BlockingQueue,我們可以直接使用ArrayBlockingQueueBlockingQueue<String> taskQueue = new ArrayBlockingQueue<>(100);// 然后我們添加三個(gè)任務(wù)WorkerThread worker = new WorkerThread(taskQueue);worker.start();taskQueue.put("Bob");Thread.sleep(1000);taskQueue.put("Alice");Thread.sleep(1000);taskQueue.put("Tim");Thread.sleep(1000);worker.interrupt();worker.join();System.out.println("END");}}class WorkerThread extends Thread{// 當(dāng)我們直接使用BlockQueue的時(shí)候,我們的代碼又被大大的簡化了BlockingQueue<String> taskQueue;public WorkerThread(BlockingQueue<String> taskQueue) {this.taskQueue = taskQueue;}@Overridepublic void run() {while(!isInterrupted()) {String name;try {// take方法就是BlockingQueue提供的一個(gè)blocking方法// 當(dāng)我們調(diào)用這個(gè)方法的時(shí)候線程會(huì)阻塞,直到條件滿足,線程才會(huì)返回name = taskQueue.take();} catch (InterruptedException e) {break;}String result = "Hello, " + name + "!";System.out.println(result);} }}直接結(jié)果和我們自己編寫原始的Block加Condition實(shí)現(xiàn)的邏輯一模一樣的,但是我們編寫的代碼被大大的簡化了
對(duì)于List來說,ArrayList是非線程安全的,線程安全的是CopyOnWriteArrayListHashMap的安全版本是ConcurrentHashMapHashSet和TreeSet對(duì)應(yīng)的是CopyOnWriteArrayList我們可以根據(jù)需要根據(jù)JDK提供的安全版本
Collections是一個(gè)工具類,例如把一個(gè)HashMap轉(zhuǎn)為一個(gè)線程安全的HashMap,我們會(huì)通過Collections.synchronizedMap(unsafeHashMap),得到一個(gè)線程安全的map.但實(shí)際上他是使用了一個(gè)包裝類,包裝了一個(gè)非線程安全的Map,然后會(huì)對(duì)所有的synchronized方法加鎖,這樣獲得線程安全比Coccurent獲得的集合效率低很多,所以我們現(xiàn)在已經(jīng)不推薦使用了.
使用java.util.cocurrent提供的Block集合可以簡化多線程編程.1. 多線程同時(shí)訪問Blocking集合是安全的2. 盡量使用JDK提供的coccurent集合,避免自己編寫同步代碼
java.util.cocurrent.atomic提供了一組原子類型的操作:例如 AtomicIntegerint addAndGet(int delta)int incrementAndGet();int get();int compareAndSet(int expect, int update);
Atomic類可以實(shí)現(xiàn):1. 無鎖(lock-free)實(shí)現(xiàn)的線程安全(thread-safe)的訪問
Compare and Set 是指在這個(gè)操作中,如果Atomic當(dāng)前的值是prev,就更新為next. 然后返回true如果prev當(dāng)前的值不等于next,就什么也不干,返回false.利用CAS操作,可以保證即使在 do...while操作中其他線程修改了Atomic的值,最終的結(jié)果也一定是正確的.
我們通過一個(gè)AtomicLong調(diào)用incrementAndGet()方法就可以非常容易的實(shí)現(xiàn)一個(gè)多線程安全的計(jì)時(shí)器
package com.leon.day05;import java.util.concurrent.atomic.AtomicInteger;class Counter {private AtomicInteger value = new AtomicInteger(0);// add方法是一個(gè)修改方法,所以用wLock,解鎖加鎖public int add(int m) {return this.value.addAndGet(m);}// 對(duì)于dec方法也是寫鎖public int dec(int m) {return this.value.addAndGet(-m);}// 但是對(duì)于get方法只需要使用一個(gè)讀鎖,這樣多個(gè)線程就可以獲取讀鎖public int get() {return this.value.get();}}public class Main {final static int LOOP = 100;// 在main方法中啟動(dòng)兩個(gè)線程,分別調(diào)用add和dec方法,public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread() {@Overridepublic void run() {for(int i=0;i<LOOP;i++) {counter.add(1);}}};Thread t2 = new Thread() {@Overridepublic void run() {for(int i=0;i<LOOP;i++) {counter.dec(1);}}};t1.start();t2.start();t1.join();t2.join();System.out.println(counter.get());}}得到的結(jié)果和synchronized和ReentrantLock是一樣的
使用java.util.atomic提供的原子操作可以簡化多線程編程.AtomicInteger/AtomicLong/AtomicIntegerArray等原子操作實(shí)現(xiàn)了無鎖的線程安全適用于計(jì)數(shù)器,累加器等
?
總結(jié)
以上是生活随笔為你收集整理的Concurrent集合 Atomic类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Condition - Java多线程编
- 下一篇: jvm结构