更新時間:2022-04-07 16:58:57 來源:動力節(jié)點 瀏覽1329次
Java并發(fā)(多線程)。本文介紹如何使用Java進行并發(fā)編程。它涵蓋了并行編程、不變性、線程、執(zhí)行器框架(線程池)、期貨、可調用的CompletableFuture和fork-join框架的概念。
并發(fā)是并行運行多個程序或程序的幾個部分的能力。如果一項耗時的任務可以異步或并行執(zhí)行,這將提高程序的吞吐量和交互性。
現(xiàn)代計算機在一個CPU中具有多個CPU或多個內(nèi)核。利用這些多核的能力可能是成功的大容量應用程序的關鍵。
一個進程獨立運行并與其他進程隔離。它不能直接訪問其他進程中的共享數(shù)據(jù)。進程的資源,例如內(nèi)存和CPU時間,是通過操作系統(tǒng)分配給它的。
線程是所謂的輕量級進程。它有自己的調用棧,但可以訪問同一進程中其他線程的共享數(shù)據(jù)。每個線程都有自己的內(nèi)存緩存。如果一個線程讀取共享數(shù)據(jù),它會將這些數(shù)據(jù)存儲在自己的內(nèi)存緩存中。
線程可以重新讀取共享數(shù)據(jù)。
默認情況下,Java應用程序在一個進程中運行。在Java應用程序中,您使用多個線程來實現(xiàn)并行處理或異步行為。
在Java應用程序中,您使用多個線程來實現(xiàn)并行處理或異步行為。并發(fā)承諾更快地執(zhí)行某些任務,因為這些任務可以分為子任務,并且這些子任務可以并行執(zhí)行。當然,運行時間受到可以并行執(zhí)行的任務部分的限制。
理論上可能的性能增益可以通過以下稱為阿姆達爾定律的規(guī)則來計算。
如果F是程序不能并行運行的百分比,N是進程數(shù),則最大性能增益為1/(F+((1-F)/N))。
線程有自己的調用棧,但也可以訪問共享數(shù)據(jù)。因此,您有兩個基本問題,可見性和訪問問題。
如果線程A讀取后來由線程B更改的共享數(shù)據(jù)并且線程A不知道此更改,則會出現(xiàn)可見性問題。
如果多個線程同時訪問和更改相同的共享數(shù)據(jù),則可能會出現(xiàn)訪問問題。
可見性和訪問問題可能導致:
活躍度失敗:由于數(shù)據(jù)并發(fā)訪問中的問題,例如死鎖,程序不再反應。
安全故障:程序創(chuàng)建了不正確的數(shù)據(jù)。
Java程序在自己的進程中運行,默認情況下在一個線程中運行。Java通過代碼支持線程作為Java語言的一部分Thread。Java應用程序可以通過此類創(chuàng)建新線程。
Java 1.5還為包的并發(fā)提供了改進的支持java.util.concurrent。
Java提供了鎖來保護代碼的某些部分,以便同時由多個線程執(zhí)行。鎖定某個方法或Java類的最簡單方法是使用synchronized關鍵字定義方法或類。
Java中的synchronized關鍵字確保:
只有一個線程可以同時執(zhí)行一段代碼
進入同步代碼塊的每個線程都會看到由同一鎖保護的所有先前修改的效果
對于線程塊的互斥訪問和線程之間的可靠通信,同步是必需的。
您可以使用synchronized關鍵字來定義方法。這將確保只有一個線程可以同時進入該方法。另一個調用這個方法的線程會一直等到第一個線程離開這個方法。
public synchronized void critial() {
// some thread critical stuff
// here
}
您還可以使用synchronized關鍵字來保護方法中的代碼塊。該塊由一個鍵保護,該鍵可以是字符串或對象。這把鑰匙叫做鎖。
所有受同一個鎖保護的代碼只能由一個線程同時執(zhí)行。
例如下面的數(shù)據(jù)結構將確保只有一個線程可以訪問add()andnext()方法的內(nèi)部塊。
package de.vogella.pagerank.crawler;
import java.util.ArrayList;
import java.util.List;
/**
* Data structure for a web crawler. Keeps track of the visited sites and keeps
* a list of sites which needs still to be crawled.
*
* @author Lars Vogel
*
*/
public class CrawledSites {
private List<String> crawledSites = new ArrayList<String>();
private List<String> linkedSites = new ArrayList<String>();
public void add(String site) {
synchronized (this) {
if (!crawledSites.contains(site)) {
linkedSites.add(site);
}
}
}
/**
* Get next site to crawl. Can return null (if nothing to crawl)
*/
public String next() {
if (linkedSites.size() == 0) {
return null;
}
synchronized (this) {
// Need to check again if size has changed
if (linkedSites.size() > 0) {
String s = linkedSites.get(0);
linkedSites.remove(0);
crawledSites.add(s);
return s;
}
return null;
}
}
}
以上就是動力節(jié)點小編介紹的"2022年Java并發(fā)-多線程的學習指南",希望對大家有幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為您服務。