本文目錄一覽:
- 1、java並發包有哪些類
- 2、求java並發編程的實例 java多線程編程例子
- 3、java 並發實現原理: 是否可以利用多線程,實現10個並發執行 請給個例子(java代碼),非常感謝!!!!
- 4、java並發框架有哪些
- 5、電腦培訓分享Java 並發編程:核心理論
- 6、「多線程」額外的並發工具類
java並發包有哪些類
1、CyclicBarrier
一個同步輔助類,允許一組線程相互等待,直到這組線程都到達某個公共屏障點。該barrier在釋放等待線程後可以重用,因此稱為循環的barrier。
來個示例:
[java] view plain copy
package test;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Recipes_CyclicBarrier {
public static CyclicBarrier barrier = new CyclicBarrier(10);
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);
for(int i=1;i=10;i++){
executor.submit(new Thread(new Runner(i+”號選手”)));
}
executor.shutdown();
}
}
class Runner implements Runnable{
private String name;
public Runner(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name + “準備好了。”);
try {
Recipes_CyclicBarrier.barrier.await(); //此處就是公共屏障點,所有線程到達之後,會釋放所有等待的線程
} catch (Exception e) {
}
System.out.println(name + “起跑!”);
}
}
2、CountDownLatch
CountDownLatch和CyclicBarrier有點類似,但是還是有些區別的。CountDownLatch也是一個同步輔助類,它允許一個或者多個線程一直等待,直到正在其他線程中執行的操作完成。它是等待正在其他線程中執行的操作,並不是線程之間相互等待。CountDownLatch初始化時需要給定一個計數值,每個線程執行完之後,必須調用countDown()方法使計數值減1,直到計數值為0,此時等待的線程才會釋放。
來個示例:
[java] view plain copy
package test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static CountDownLatch countDownLatch = new CountDownLatch(10);//初始化計數值
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);
for(int i=1;i=10;i++){
executor.submit(new Thread(new Runner1(i+”號選手”)));
}
executor.shutdown();
}
}
class Runner1 implements Runnable{
private String name;
public Runner1(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name + “準備好了。”);
CountDownLatchDemo.countDownLatch.countDown(); //計數值減1
try {
CountDownLatchDemo.countDownLatch.await();
} catch (Exception e) {
}
System.out.println(name + “起跑!”);
}
}
3、CopyOnWriteArrayList CopyOnWriteArraySet
CopyOnWriteArrayList CopyOnWriteArraySet是並發容器,適合讀多寫少的場景,如網站的黑白名單設置。缺點是內存佔用大,數據一致性的問題,CopyOnWrite容器只能保證數據最終的一致性,不能保證數據實時一致性。鑒於它的這些缺點,可以使用ConcurrentHashMap容器。
實現原理:新增到容器的數據會放到一個新的容器中,然後將原容器的引用指向新容器,舊容器也會存在,因此會有兩個容器佔用內存。我們也可以用同樣的方式實現自己的CopyOnWriteMap。
4、ConcurrentHashMap
ConcurrentHashMap同樣是一個並發容器,將同步粒度最小化。
實現原理:ConcurrentHashMap默認是由16個Segment組成,每個Segment由多個Hashtable組成,數據變更需要經過兩次哈希演算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只會將單個Segment鎖住,然後操作Segment下的Hashtable,多個Segment之間不受影響。如果需要擴容不是對Segment擴容而是對Segment下的Hashtable擴容。雖然經過兩次哈希演算法會使效率降低,但是比鎖住整個容器效率要高得多。
5、BlockingQueue
BlockingQueue只是一個介面,它的實現類有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。
ArrayBlockingQueue:由數據支持的有界阻塞隊列。
LinkedBlockingQueue:基於鏈接節點、範圍任意的阻塞隊列。
PriorityBlockingQueue:無界阻塞隊列。
SynchronousQueue:一種阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作。
DelayQueue:Delayed元素的一個無界阻塞隊列。
LinkedBlockingDeque:基於鏈接節點、範圍任意的雙端阻塞隊列,可以在隊列的兩端添加、移除元素。
6、Lock
Lock分為公平鎖和非公平鎖,默認是非公平鎖。實現類有ReetrantLock、ReetrantReadWriteLock,都依賴於AbstractQueuedSynchronizer抽象類。ReetrantLock將所有Lock介面的操作都委派到Sync類上,Sync有兩個子類:NonFairSync和FaiSync,通過其命名就能知道分別處理非公平鎖和公平鎖的。AbstractQueuedSynchronizer把所有請求構成一個CLH隊列,這裡是一個虛擬隊列,當有線程競爭鎖時,該線程會首先嘗試是否能獲取鎖,這種做法對於在隊列中等待的線程來說是非公平的,如果有線程正在Running,那麼通過循環的CAS操作將此線程增加到隊尾,直至添加成功。
7、Atomic包
Atomic包下的類實現了原子操作,有對基本類型如int、long、boolean實現原子操作的類:AtomicInteger、AtomicLong、AtomicBoolean,如果需要對一個對象進行原子操作,也有對對象引用進行原子操作的AtomicReference類,還有對對象數組操作的原子類:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然後調用底層操作系統指令來實現。
求java並發編程的實例 java多線程編程例子
不懂……如果你是用線程同時去添加多個用戶,第一,人不是多線程的,你只能一個個去添加;第二,如果你想添加用戶的時候還沒有添加完成又做別的事情,完成可能用面向對象思想,程序一塊塊執行的,對於編人員來說不用考慮到多線程,程序本身已經完成了,比如我點擊了添加用戶的按鈕,你的程序還可以往下跑,因為你僅僅是new了一個添加用戶的窗口,主程序可以繼續向下執行,除非你玩模態對話;第三,如果你非要多線程添加用戶,就用簡單的線程例子能解決啊,public void run(){}方法里寫上添加用戶的代碼就行啦,主程序運行時new 你寫好的線程類(YouThread implements Runnable{public void run(…)}),啟動它(new Thread(new YouThread()).start());之後寫上自己要繼續執行的代碼
java 並發實現原理: 是否可以利用多線程,實現10個並發執行 請給個例子(java代碼),非常感謝!!!!
public static void main(String[] args) {
for(Thread t:getThreads()){
t.start();
}
}
public static Thread[] getThreads(){
Thread[] thread = new Thread[10];
for(int i=0;i10;i++){
final Integer num = new Integer(i);
thread[i] = new Thread(new Runnable(){
public void run() {
int j=5;
while(j–0){
System.out.println(“this is thread”+num);
}
}
});
}
return thread;
}
java並發框架有哪些
Java並發框架java.util.concurrent是JDK5中引入到標準庫中的(採用的是Doug
Lea的並發庫)。該包下的類可以分為這麼塊:
Executors
1)介面:
Executor(例子涉及):用來執行提交的Runnable任務的對象。是一個簡單的標準化介面,用來定義包括線程池、非同步IO、輕量級任務框架等等。任務可以由一個新創建的線程、一個已有任務執行線程、或是線程直接調用execute()來執行,可以串列也可並行執行,取決於使用的是哪個Executor具體類。
ExecutorService(例子涉及):Executor的子介面,提供了一個更加具體的非同步任務執行框架:提供了管理結束的方法,以及能夠產生Future以跟蹤非同步任務進程的方法。一個ExcutorService管理著任務隊列和任務調度。
ScheduledExecutorService(例子涉及):ExecutorService的子介面,增加了對延遲和定期任務執行的支持。
Callable(例子涉及):一個返回結果或拋出異常的任務,實現類需要實現其中一個沒有參數的叫做call的方法。Callabe類似於Runnable,但是Runnable不返回結果且不能拋出checked
exception。ExecutorService提供了安排Callable非同步執行的方法。
Future(例子涉及):代表一個非同步計算的結果(由於是並發執行,結果可以在一段時間後才計算完成,其名字可能也就是代表這個意思吧),提供了可判斷執行是否完成以及取消執行的方法。
2)實現:
ThreadPoolExecutor和ScheduledThreadPoolExecutor:可配置線程池(後者具備延遲或定期調度功能)。
Executors(例子涉及):提供Executor、ExecutorService、ScheduledExecutorService、ThreadFactory以及Callable的工廠方法及工具方法。
FutureTask:對Future的實現
ExecutorCompletionService(例子涉及):幫助協調若干(成組)非同步任務的處理。
Queues
非阻塞隊列:ConcurrentLinkedQueue類提供了一個高效可伸縮線程安全非阻塞FIFO隊列。
阻塞隊列:BlockingQueue介面,有五個實現類:LinkedBlockingQueue(例子涉及)、ArrayBlockingQueue、SynchronousQueue、PriorityBlockingQueue和DelayQueue。他們對應了不同的應用環境:生產者/消費者、消息發送、並發任務、以及相關並發設計。
Timing
TimeUnit類(例子涉及):提供了多種時間粒度(包括納秒)用以表述和控制基於超時的操作。
Synchronizers 提供特定用途同步語境
Semaphore(例子涉及):計數信號量,這是一種經典的並發工具。
CountDownLatch(例子涉及):簡單的倒計數同步工具,可以讓一個或多個線程等待直到另外一些線程中的一組操作處理完成。
CyclicBarrier(例子涉及):可重置的多路同步工具,可重複使用(CountDownLatch是不能重複使用的)。
Exchanger:允許兩個線程在匯合點交換對象,在一些pipeline設計中非常有用。
Concurrent Collections
除隊列外,該包還提供了一些為多線程上下文設計的集合實現:ConcurrentHashMap、CopyOnWriteArrayList及CopyOnWriteArraySet。
注意:”Concurrent”前綴的類有別於”synchronized”前綴的類。「concurrent」集合是線程安全的,不需要由單排斥鎖控制的(無鎖的)。以ConcurrentHashMap為例,允許任何數量的並發讀及可調數量的並發寫。「Synchronized」類則一般通過一個單鎖來防止對集合的所有訪問,開銷大且伸縮性差。
電腦培訓分享Java 並發編程:核心理論
並發編程是Java程序員最重要的技能之一,也是最難掌握的一種技能。它要求編程者對計算機最底層的運作原理有深刻的理解,同時要求編程者邏輯清晰、思維縝密,這樣才能寫出高效、安全、可靠的多線程並發程序。電腦培訓發現本系列會從線程間協調的方式(wait、notify、notifyAll)、Synchronized及Volatile的本質入手,詳細解釋JDK為我們提供的每種並發工具和底層實現機制。在此基礎上,我們會進一步分析java.util.concurrent包的工具類,包括其使用方式、實現源碼及其背後的原理。本文是該系列的第一篇文章,是這系列中最核心的理論部分,之後的文章都會以此為基礎來分析和解釋。
關於java並發編程及實現原理,還可以查閱《Java並發編程:Synchronized及其實現原理》。
一、共享性
數據共享性是線程安全的主要原因之一。如果所有的數據只是在線程內有效,那就不存在線程安全性問題,這也是我們在編程的時候經常不需要考慮線程安全的主要原因之一。但是,在多線程編程中,數據共享是不可避免的。最典型的場景是資料庫中的數據,為了保證數據的一致性,我們通常需要共享同一個資料庫中數據,即使是在主從的情況下,訪問的也同一份數據,主從只是為了訪問的效率和數據安全,而對同一份數據做的副本。我們現在,通過一個簡單的示例來演示多線程下共享數據導致的問題。
二、互斥性
資源互斥是指同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。我們通常允許多個線程同時對數據進行讀操作,但同一時間內只允許一個線程對數據進行寫操作。所以我們通常將鎖分為共享鎖和排它鎖,也叫做讀鎖和寫鎖。如果資源不具有互斥性,即使是共享資源,我們也不需要擔心線程安全。例如,對於不可變的數據共享,所有線程都只能對其進行讀操作,所以不用考慮線程安全問題。但是對共享數據的寫操作,一般就需要保證互斥性,上述例子中就是因為沒有保證互斥性才導致數據的修改產生問題。
「多線程」額外的並發工具類
Java的結合框架提供了位於java.util包下的諸多介面和類。其中介面包括了List、Set 和 Map。類包括 ArrayList、TreeMap 和 HashMap。 ArrayList、TreeMap 和 HashMap 以及實現類這些介面的類都不是線程安全的。不過你可以使用類java.util.Collections中的同步包裝方法 讓他們變得安全。舉個栗子,可以向Collections.synchronizedList()中傳入一個ArrayList實例,已獲得一個線程安全的ArrayList。
線程安全的集合存在的問題:
那怎麼辦呢?使用並發工具類
並發工具類使用並發集合來應對這些問題,並發集合具有並發性能和高擴展行、面向集合的類型,他們存儲在java.util.concurrent 包中,面向結合的類返回了弱一致性的迭代器
弱一致性迭代器具有的屬性
前面我們通過wait() 和 notify()實現了生產者-消費者應用, 有了 BlockingQueue 其實代碼可以更簡單。
如果發現列印順序錯亂,別忘了使用 synchronized 或者 lock/unlock 來同步代碼塊。
類 ConcurrentHashMap 和 HashMap 在行為上沒啥區別,但無需顯示同步就可以工作於多條線程的上下文。
看個熟悉的列子:你經常需要檢查一個 map 中是否包含某個特定的值,當這個值不存在的時候,將它放進 map 中;
乍一看沒啥問題,但是放在多線程的環境中,他卻不是線程安全的。 map.containsKey()和 map.put() 方法之間,其他線程可能插入了這個條目,很可能會被覆蓋掉。 為了消除這個競態條件,你必須顯示的同步這段代碼
上面synchronized這段代碼保證了可見性,但是在線程高爭用環境下影響性能,還可能發生死鎖之類的活躍性問題。 那如何用原子變數來代替synchronized關鍵字呢?看下面的例子
Java低級的同步機制,強制使用互斥以及可見性,以如下的方式影響了硬體的使用和擴展能力。
你會認為 volatile 是同步的備胎,但 volatile 變數也只能解決可見性問題,無法應用於安全的實現原子的 讀-改-寫 的序列。這個原子的序列對於 實現線程安全的計數器以及其他需要互斥訪問的實體是需要的。並發工具集提供了另一個備胎,即 compare-and-swap。
Compare-and-swap(CAS) 是針對非搶佔式微處理器的一條指令的寬泛術語。這條指令讀取內存的位置, 比較讀到的值和期望的值,當讀到的值和期望的值匹配時,就將期望的值存儲到該內存的位置;否則什麼事也不會發生。 現代微處理提供了多種 CAS 的變體, CAS 支持 讀-改-寫 的序列 1,從地址 A 讀出值 x; 2,在 x 上進行一個多步計算,衍生出一個新值 y; 3,使用 CAS 把 A 的值從 x 改成 y。當操作這些步驟時,如果 A 的值沒有發生改變,CAS 就成功了。
最終,JDK通過CPU的cmpxchgl指令的支持,實現AtomicInteger的CAS操作的原子性。
public ForkJoinPool() 以 Runtime.getRuntime().availableProcessors()的返回值作為 parallelism 來創建 ForkJoinPool
看代碼更親切
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/257735.html