免費網站java源碼大全:java項目案例分析

在計算機世界中,並發是指一系列相互無關的任務在一台計算機上同時運行。對於有多個處理器或者多核處理器的計算機來說,這個同時性是真實發生的。然而,對於只有單核處理器的計算機來說,它僅僅是表面現象。

所有現代操作系統均支持並發地執行任務。用戶可以在聽音樂或者瀏覽網頁的同時閱讀郵件。這種並發是進程級別的並發。在同一進程內,也可以有多種同時運行的子任務,我們將這些並發的子任務稱為線程。與並發性有關的另一個概念是並行性( parallelism )。雖然它與並發性的概念不同,但是有一定聯繫。一些學者認為,當多線程應用程序運行在單核處理器上時,程序就是並發運行的;當多線程應用程序運行在多個處理器或者多核處理器上時,程序就是並行運行的。還有一些學者認為,多線程應用程序的線程執行順序若不是預先定義的,程序就是並發運行的;如果多線程應用程序的線程按照指定順序執行,那麼這個程序就是並行運行的。

本章介紹了如何使用Java 9 API來進行基本的線程操作,包括創建和運行線程、處理線程內拋出的異常、將線程分組,並將分組作為一個整體處理組內的線程。

1.2線程的創建、運行和設置

本節介紹如何使用Java APl對線程進行基本的操作。與Java語言中的基本元素一樣,線程也是對象(Object )。在Java中,創建線程的方法有以下兩種。

直接繼承Thread類,然後重寫run()方法。

構建一個實現Runnable接口的類並重寫run()方法,然後創建該類的實例對象,並以其作為構造

參數去創建Thread類的對象。建議首選這種方法,因為它可以帶來更多的擴展性。

在本節中,我們將採用第二種方法創建線程,然後學習如何改變線程的屬性。Thread類包含如下一些信息屬性,它們能夠輔助區分不同的線程、反映線程狀態、控制其優先級等。

ID:該屬性存儲了每個線程的唯一標識符。

Name :該屬性存儲了線程的名字。

Priority:該屬性存儲了 Thread對象的優先級。在Java 9中,線程優先級的範圍為1-10 ,其中1表示最低優先級, 10表示最高優先級。通常不建議修改線程的優先級。線程優先級僅供底層操作系統作為參考,不能保證任何事情,如果一定要修改,請知曉優先級僅僅代表了一種可能性。

Status :該屬性保存了線程的狀態。在Java中,線程有6種狀態-Thread.State枚舉中定義這些狀態: NEW、 RUNABLE 、 BLOCKED 、wAITING、TIMED_MAIING和TERMINATED 。這些狀態的具體意義如下。

NEW: 線程已經創建完畢但未開始執行。

RUNNABLE: 線程正在JVM中執行。

BLOCKED: 線程處於阻塞狀態,並且等待獲取監視器。

WAITING: 線程在等待另一個線程。

TIMED-MAITING: 線程等待另一個線程一定的時間。

TERMTNATED: 線程執行完畢。

本節將在一個案例中創建10個線程來找出20000以內的奇數。

項目準備

本案例是用Eclipse IDE實現的。如果開發者使用Eclipse或者其他IDE (例如NetBeans ) ,則應打開它並創建一個新的Java項目。

案例實現

根據如下步驟實現本案例

1,創建一個名為calculator的類,並實現Runnable接口:

Public class Calculator implements Runnable{

2,實現run()方法。在這個方法中,存放着線程將要運行的指令。在這裡,這個方法用來計算20000以內的奇數

@Override
public void run()
long current =1L;
long max =20000L;
long numPrimes = OL;
System.out.printf("Thread '%s': STARTn"
Thread.currentThread().getName());
while (current <=max)
if (isPrime(current)){
numPrimes++;
}
current++;
}
System.out.printf("Thread '%s'; END. Number of Primes: %dn"
Thread.currentThread() .getName(), numPrimes);
}

3.實現輔助方法isprime() 。該方法用於判斷一個數是否為奇數:

private boolean isPrime (long number) {
if (number <=2){
return true;
}
for (long i =2; i<inumber; i++){
if ((number % i) ==0){
return false;
}
return true;
}
}

4,實現應用程序的主方法,創建包含main()方法的Main類:

public class Main {
public static void main(String[] args) {

5,首先,輸出線程的最大值、最小值和默認優先級:

System.out.printf("minimum Priority: %sn",
Thread.MIN_PRIORITY);
System.out, printf{"Normal Priority: %sn",
Thread. NORM_PRIORITY);
System.out.printf("Maximun Priority: %sn",
Thread.MAX_PRIORITY);

6,創建10個 Thread對象,分別用來執行10個 calculator 任務。再創建兩個數組,用來保存

Thread 對象及其State 對象。後續我們將用這些信息來查看線程的狀態。這裡將5個線程設置為最大優先級,另5個線程設置為最小優先級:

Thread threads [];
Thread,state status[];
threads = new Threadr10];
status = new Thread.Stater[10];
for (int i = 0; i < 10; i++){
threads[i] = new Thread (new Calculator());
ir ((i% 2) ==0) {
threads [i].setPriority(Thread.MAX_PRIORITY);
}else{
threads[i].setpriority(Thread.MIN_PRIORITY));
}
threads[i].setName("My Thread"+i);
}

7,接着將一些必要的信息保存到文件中,因此需要創建try-with-resources語句來管理文件。在這個代碼塊中,先將線程啟動前的狀態寫入文件,然後啟動線程:

try (Filewriter file = new Filewriter(".\data\log.txt");
Printwriter pw = new Printwriter(file);){
for (int i =0; i <10; i|++){
pw.println("Main : Status of Thread "+i+":"+
threads[i].getstate());
status[i] = threads[i].getstate();
}
for (int i =0; i < 10; i++){
threads[i].start();
}

8,等待線程運行結束。在1.6節中,我們將用join()方法來等待線程結束。本案例中,由於我們需要記錄線程運行過程中狀態的轉變,因此不能使用join()方法來等待線程結束,而應使用如下代碼:

boolean finish = false:
while (!finish){
for (int i =0; i<10; i++){
if (threads[i].getstate() != status[i]) {
writeThreadInfo(pw, threads[i], status [i]);
status[i] = threads[i].getstate();
}
}
finish =true;
for (int i =0; i<10; i++) {
finish =finish && (threads[i].getstate() ==
State. TERMINATED);
}
}
}catch (IOException e){
e.printstackTrace();
}
}

9,在上述代碼中,我們通過調用writeThreadInfo()方法來將線程信息記錄到文件中。代碼如下:

private static void writeThreadInfo(PrintWriter pw,
Thread thread,
state state) {
pw.printf("Main: Id %d -%sn", thread.getId(),
thread.getName());
pw.printf("Main: priority:%dn", thread.getPriority());
pw.printf ("Main: Old state: %sn", state);
pw.printf ("Main: New State: %sn", thread.getstate());
pw.printf("Main :***********************************************n");
}

10,運行程序,然後觀察不同的線程是如何同時運行的。

結果分析

下圖是程序在控制台的輸出,從中可以看到,線程正在並行處理各自的工作。

Java 並發編程實戰:如何創建並運行java線程

從下面的屏幕截圖中可以看到線程是如何創建的,擁有高優先級的偶數編號線程比低級優先級的奇數編號線程優先執行。該截圖來自記錄線程狀態的log.tet文件。

Java 並發編程實戰:如何創建並運行java線程

每個Java應用程序都至少有一個執行線程。在程序啟動時, JVM會自動創建執行線程運行程序的main()方法

當調用Thread 對象的start()方法時,JVM才會創建一個執行線程。也就是說,每個Thread對象的start()方法被調用時,才會創建開始執行的線程。

Thread類的屬性存儲了線程所有的信息。操作系統調度執行器根據線程的優先級,在某個時刻選擇一個線程使用CPU ,並且根據線程的具體情況來實現線程的狀態。

如果沒有指定線程的名字,那麼JVM會自動按照Thread -xx格式為線程命名,其中xx是一個數字。線程的ID和狀態是不可修改的,事實上, Thread類也沒有實現setIa()和setstatus()方法,因為它們會引入對ID和狀態的修改。

一個Java程序將在所有線程完成後結束。初始線程(執行main()方法的線程)完成,其他線程仍會繼續執行直到完成。如果一個程調用system.exit()命令去結束程序,那麼所有線程將會止各自的運行。

創建一個Thread對象並不意味着會創建一個新的執行線程。同樣,調用實現Runnable接口類的run()方法也不會創建新的執行線程。只有調用了start()方法,一個新的執行線程才會真正創建。

其他說明

正如本節開頭所說,還有另一種創建執行線程的方法——實現一個繼承Thread的類,並重寫其

run()方法,創建該類的對象後,調用start()方法即可創建執行線程。

可以使用Thread類的靜態方法 currentThread()來獲取當前運行線程的Thread對象。

調用setpriority()方法時,需要對其拋出的IllegalArgumentException 異常進行處理,以防傳入的優先級不在合法範圍內(1和10之間)。

本文節選自《Java 9 並發編程實戰》

Java 並發編程實戰:如何創建並運行java線程

本書將帶你了解所有的新API,向您展示如何構建並行多線程應用程序。這本書涵蓋了所有Java並發API的元素,包括基本配方,這些幫助您利用激動人心的新功能。您將學習如何使用並行和反應流來處理大規模數據集。接下來,您將繼續創建流,並使用他們所有中間和終端的操作以一種並行且函數性的方式來進行數據的收集。此外,你會了解一系列的實戰方式,如線程管理、同步、執行人、並行和反應流等。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/219175.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 10:55
下一篇 2024-12-09 10:55

相關推薦

發表回復

登錄後才能評論