併發程式設計主要目的是為了在相同的時間內讓程式執行得更快或者處理更多的任務。為了實現這一目的,併發程式設計會面臨很多的挑戰。併發程式設計必然會帶來多執行緒之間的問題,比如上下文之間的切換,執行緒死鎖,以及硬體資源的限制。
無論是單核還是多核處理器都支援多執行緒。在單核處理器中,cpu會給每個執行緒分配時間片來實現多執行緒,其實這是一種錯覺,單核處理器在不停的進行執行緒之間的切換,時間片非常短,以至於我們無法通過肉眼感知。
cpu通過核心排程來分配時間片。當前執行緒時間片執行完成後會切換到另乙個執行緒。在進行執行緒切換的時候會儲存上乙個時間片任務的狀態,以便下次切換回這個任務時,可以再載入這個任務的狀態。所以任務從儲存到再載入的過程就是一次上下文切換。
1.1:多執行緒的使用
使用的執行緒越多,上下文的切換越頻繁。比如核心分配的時間片是20ms,做程序切換的時間是1ms,那麼如果需要處理的任務在20ms中無法完成,就需要額外增加1ms的上下文切換消耗。
private static final longcount結果:上述**中兩個方法執行的時間無法確定,數量越大,多執行緒的速度越快,這個也取決於cpu的效能。在數量很小的時候,序列的方法速度很快。原因有兩點:(1)建立執行緒對於系統的開銷比較大;(2)序列沒有上下文的切換。= 100000000
;public static void
main(string args)throws
exception
private static void
concurrencymethod1()throws
interruptedexception
}});
thread.start();
int
b = 0;
for
(long
i =
0; i <count
; i++)
long
time = system.
currenttimemillis
() - start;
thread.join();
system.out
.println("concurrency :"
+ time +"ms,b="
+ b);
}private static void
serialmethod2()
int
b = 0;
for
(long
i =
0; i <count
; i++)
long
time = system.
currenttimemillis
() - start;
system.out
.println("serial:"
+ time +"ms,b="
+ b +",a="
+ a);
}
1.2:減少上下文的切換
既然知道上下文切換會帶來一些效能上的問題,那麼我們應該如何減少上下文的切換呢?有以下幾種方式:
減少上下文的切換主要就是通過減少不必要的執行緒數。
在併發程式設計中,為了保證操作的原子性,我們會經常使用鎖。在開發中,鎖是個非常有用的工具,使用的場景非常多,使用起來比較簡單。但同時它也會帶來一些問題,可能會引起死鎖,一旦產生死鎖,會導致系統擁堵,嚴重情況下系統直接不可使用。下面這段**演示了死鎖的一種情況
public static void這裡的**只是演示效果,一般情況下不會出現這樣的問題。但如果不能保證拿到鎖的物件及時釋放鎖,這會產生很嚴重的問題。撐爆硬體資源,直接導致系統不可用。以下是幾種避免死鎖的方式:main(string args)
});thread t1 =new
thread(new
runnable()
});t2.start();
t1.start();
}private static void
deadlock(string code, string threadname) }}
(1)什麼是資源限制
程式在執行時依賴於計算機的硬體和軟體。比如說程式上傳乙個10gb的大資源,這時計算機的頻寬,硬碟的讀寫速度等會帶來一些影響。上傳資源的速度限制為20m/s,那麼不考慮其他因素,理想情況下至少需要10 * 1024 /20的時間。就算將10gb的資源切割成10個1gb的資源一起上傳,但最終上傳的限制依舊是20m/s,對於上傳的速度不會帶來提公升。
軟體資源限制有資料庫的連線數和socket連線數等。
(2)資源限制引發的問題
在併發程式設計中,將**執行速度加快的原則是將**中序列執行的部分變成併發執行。但是如果將某段序列的**併發執行,因為受限於資源,仍然在序列執行,這時候程式不僅不會加快執行,反而會更慢,因為增加了上下文切換和資源排程的時間。
(3)如何解決資源限制的問題
對於硬體資源限制,可以垂直提公升硬體,比如說提公升伺服器的配置,增強處理器,放大頻寬等。對於軟體資源限制,執行緒池的復用,連線池的復用。
(4)在資源限制情況下進行併發程式設計
程式的執行必然會受到硬體和軟體資源的限制。如何在資源限制的情況下,讓程式執行得更快呢?最重要的方法就是,根據不同的資源限制調整程式的併發度。
java併發程式設計學習(3)
銀行排隊叫號的場景如圖所示 有乙個出票機,按順序出票。有多個櫃檯叫號。對於這樣的場景,實現可以分為2部分,出票機和櫃檯。出票機public class ticketwindow implements runnable catch interruptedexception e 新建ticketwind...
java併發程式設計實踐學習
1.futuretask有個簡單理解,但是例子不是非常懂,get 是返回結果,沒有結果的話阻塞,為什麼能處理耗時的計算操作呢?2.copyonwritearraylist究竟在什麼時候複製啊?2013 2 20 p294 清單14.3是什麼意思,先驗條件在 用到了 2013 2 21 p294 29...
學習java併發程式設計(一)
1 任務的認識 任務可以看作是乙個implements runnable的乙個類,任務的內容就是定義在run 方法中的內容 2 thread executor 當使用new thread runnable r start 時,即客戶端 也就是編寫程式的開發人員 直接在新執行緒中執行任務,而在使用ex...