日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 里的thread (线程)简介

發布時間:2025/3/20 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 里的thread (线程)简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Java里 thread 就是線程的意思.

說到線程的概念, 自然離不開另外兩個詞: 程序和進程.

從最基本的程序講起:


一. 什么是程序(Program)

所謂程序, 就是1個嚴格有序的指令集合. 程序規定了完成某一任務時,計算機所需要做的各種操作, 以及操作的順序.


1.1 單道程序運行環境

所謂單道程序環境就是指, 計算機除了操作系統之外, 只允許運行1個用戶程序.

以前的DOS系統就是1個典型的單道程序運行環境.


單道程序有如下特點:

1. 資源的獨占性: 任何時候, 內存內只有1個用戶程序, 這個程序獨享系統的所有資源.

2. 執行順序性: 內存中只執行1個程序, 各程序是按次序執行的, 即是做完1件事后, 才做另一件事.

??????????? 絕不可能執行1個程序的中途暫停, 然后去執行另1個程序.

3.結果的再現性: 只要執行環境和初始條件相同, 重復執行1個程序, 獲得的結果總是一樣的.


1.2 多道程序運行環境

所謂多道程序運行環境是指, 計算機除了操作系統之外, 允許同時運行多個用戶程序.

當今的unix, linux都是典型的多道程序運行環境.


多道程序有如下特點:

1. 間斷性: 也就是cpu會在多個程序之間切換執行, 例如cpu執行程序A一段時間后, 會切換去執行程序B一段時間.

????????????????? 由于這個時間段很短, 所以對用戶造成1個程序A和程序B同時執行的假象.


2. 失去封閉性:? 程序執行受外界影響, 也就是多個程序之間共享資源, 互相制約.

3. 不可再現性:? 重復執行時, 可能得到不同的結果. 原因就是上面的點, 執行時可能會受到內存中其他程序的影響.

二. 什么是進程(process)

進程這個概念是基于多道程序運行環境來講的.?

1個進程就是程序在內存中運行的1個實例


由于在多道程序運行環境中, 同1個程序可以同時產生兩個實例在內存里運行.


舉個簡單例子:? 例如你可以在操作系統打開兩個gvim 文本編輯器, 同時編輯兩個不同的文件.

這時執行ps -ef | grep gvim 就會見到系統中有兩個名字是gvim的進程, 但是它們的進程id是不同的.


也就是將,? gvim這個程序在內存中生成兩個進程同時運行.


在多道程序運行環境中.? 引用進程這個概念來描敘程序在內存里事例, 用來區別于程序本身.


真正深入了解進程并不簡單, 進程其實算是屬于操作系統這門課的范疇. 1個進程包括程序段, 數據段, 程序控制塊等,? 但是作為一個普通的程序猿, 沒必要理解得這么深入.


三. 什么是線程(thread).

相對地, 我認為作為1個普通的程序猿, 必須深入了解線程這個概念.


其實, 線程就是1個進程的執行路徑.

一般的java程序都是從啟動類的main函數入口開始執行, main函數的結束而停止.?? 這條執行路徑就是java程序的主線程.


也就是講:

線程是相對于進程來講的, 1個進程至少存在1條線程.


而java允許多線程編程, 也就是1個進程除主線程外,? 還允許存在1個或若干個其他線程, cpu會在這些線程當中間斷切換執行, 給用戶造成同時執行的假象.



四. 1個單線程java程序的簡單例子.

例子如下:

package Thread_kng;class S_thrd_1{public void f(){while (true){System.out.printf("Thread main is runing!\n");}//System.out.printf("f() is done!\n"); //compilation fail} }public class S_thread_expl{public static void g(){S_thrd_1 s = new S_thrd_1();s.f(); System.out.printf("g() is done!\n");} }

上面的例子中,? g() 函數調用了f() 函數,

g()函數在最后嘗試輸出"g() is done!" , 但是因為f() 是一個無限循環.? 所以g() 調用f()后, 根本沒機會執行后面的語句!


也就是說, 雖然g() 跟 f() 是兩個不同類的函數, 但是它們是在程序中的同一個線程(主線程)內執行.???

在同一個線程內, 語句總是按程序猿編寫的順序依次執行, 一條語句未執行完時, 不會跳到后面執行其他的語句.



五. 1個多線程java程序的簡單例子.

例子如下:

package Thread_kng;class M_thrd_1 extends Thread{ //extendspublic M_thrd_1(String name){super(name);}public void run(){ //overwrite the method run() of superclasswhile (true){System.out.printf("Thread " + this.getName()+ " is runing!\n");}//System.out.printf("f() is done!\n"); //compilation fail} }public class M_thread_expl{public static void g(){M_thrd_1 s = new M_thrd_1("T1");s.start(); //start()method is extended from superclass, it will call the method run()M_thrd_1 s2 = new M_thrd_1("T2");s2.start();System.out.printf("g() is done!\n");}


上面例子中, 類 M_thrd_1繼承了線程類Thread.? 并重寫了run方法.

在下面的g()函數中.

實例化了兩個類M_thrd_1的對象s, s1 的對象.

執行了start()方法.

start()方法繼承字Thread, 它會啟動1新線程, 并調用run()函數.

而g()后面本身也在不斷循環輸出"THread Main is running"


所以輸出如下:





可以 見到, 輸出結果是T1,T2 和Main 交替輸出在屏幕上.


實際上, 這個程序有3個線程.

其中1個就是主線程.

主線程main通過實例化兩個M_thrd_1的對象, 調用其start()函數開啟了兩個子線程.

其中1個子線程不斷輸出T1

另1個子線程不斷輸出T2


但是主線程并不會等待其子線程執行完成, 會繼續執行下面的代碼,所以不斷循環輸出Main!


所以這個例子實際上要3個線程在輸出信息到屏幕了!


六. Java 開啟一條新進程的兩種方式.

java開啟一條新線程, 有兩種方式. 但是都要利用java的線程基類Thread.


6.1 方式1. 創建Thread的派生類

這個就類似上面的例子:

具體步驟如下:


6.1.1 線程準備: 新建1個類, 繼承線程類Thread.? 將業務代碼寫入重寫后的run() 方法中.

例如上面的例子中的M_thrd_1類

class M_thrd_1 extends Thread{ //extendspublic M_thrd_1(String name){super(name);}public void run(){ //overwrite the method run() of superclasswhile (true){System.out.printf("Thread " + this.getName()+ " is runing!\n");}//System.out.printf("f() is done!\n"); //compilation fail} }
可以見到, 我們將線程要執行的業務代碼寫入了run() 方法.



6.1.2 啟動線程: 新建1個上述類的對象, 運行start()方法

例如

M_thrd_1 s = new M_thrd();

s. start();


其中start() 是類M_thrd_1 繼承自超類Thread的.

我們看看JDK API 對start() 方法的定義:


?void? start()
??????????使該線程開始執行;Java 虛擬機調用該線程的 run 方法。


可以見到, 調用了start() 方法后, 會開始執行改線程, 也就是在當前線程下開啟一條新線程.

而這條新線程做什么呢, 就是執行run()里面的代碼.


所以我們一般只需要把也業務的代碼寫入run()里面就ok了. 不要重寫start()方法.


注意, 如果直接執行s.run(); 則會在當前線程下執行run里面的代碼, 并沒有開啟一條新線程. 區別很大的.



6.2 方式2. 創建1個類, 實現Runnable 接口

步驟跟上面的方式差別不大

6.2.1 線程準備: 新建1個類, 實現接口Runnable. 將業務代碼寫入重寫后的run() 方法中.

例子:

class M_thrd_2 implements Runnable{ //extendspublic int id = 0;public void run(){ //overwrite the method run() of superclasswhile (true){System.out.printf("%s: Thread " + this.id+ " is runing!\n", Thread.currentThread().getName());}//System.out.printf("f() is done!\n"); //compilation fail} }

上面的例子 M_thrd_2 就實現了接口Runnable

并重寫了接口Runnable 的抽象方法run();


注意.? currentThread() 是類Thread的一個靜態方法, 作用是獲取當前語句所在的線程.


6.2.2 啟動線程: 新建1個上述類的對象s, 在新建1個類Thread的對象t, 把s作為一個參數用于t的構造方法.? 并執行t.start()

貌似比方式一復雜.

其實非如下:

new Thread(new M_thrd_2()).start()


例子:

public class M_thread_expl2{public static void g(){M_thrd_2 s = new M_thrd_2();s.id = 1;Thread t1 = new Thread(s);t1.start();Thread t2 = new Thread(s);s.id = 2;t2.start();} }

在g() 函數中,

首先新建1個類M_thrd_2的 對象s.

并利用s作為參數 建立了兩個線程類Thread的對象t1 和 t2. 并啟動這兩個線程.


注:

1. 這個例子中有3個線程, 其中1個主線程(也就是g() 函數所在的線程). 開啟了兩個子線程, 該兩個子線程都在不斷循環輸出信息到屏幕上.

2. Thread(object ob) 是1個屬于類Thread的構造方法,? 其中的對象ob 必須實現Runnable 接口.

3. 這個例子執行時 , 第一個t1首先會輸出id = 1,??? 但是當第二個線程t2開始執行后, t1會輸出id=2,? 因為t1, 和t2都是利用同1個對象建立的.

??? 也就是說, 這個對象的變動會同時影響兩個線程.


輸出如下:




6.3 兩種方式的區別

1.? 方式1是創建繼承類Thread的派生類,? 方式2是創建實現Runnable接口的類.

2.? 啟動方式:? 方式1是直接調用業務類的對象的start()方法, 方式2是利用業務類類的對象新建1個類Thread的對象, 并調用該對象的start()方法.

3.? 如果要啟動多個線程, 通過方式1需要新建多個不同業務類的對象, 方式2 則可以通過業務1個對象 構建多個Thread類對象, 但是業務對象的變動會同時影響對應的多個線程.



七. 關于線程的一些常用方法介紹.

7.1 run()

我們要吧線把要執行的業務代碼寫入這個方法. 上面提過了.? 注意, 如果我們直接執行1個線程對象的run()方法可以合法的, 但是仍然是在當前線程內執行, 并沒有開始一條新線程.


7.2 Start()

當1個線程or其派生類執行1個start()方法. 就開啟1個新線程, 并調用該類的run()方法.

注意: 1個線程如果已經調用過一次start(), 再調用start()則或拋異常.


7.3 stop()

停止1個1個線程.


7.4 setName() 和 getName()

設置和獲得對應線程的名字.


7.5 Thread.currentThread()

注意這個方法是一個static方法,? 而上面的都不是靜態方法.


這個方法返回當前執行語句所屬的線程.


例如1個線程對象A.??? 它的run() 方法里調用了 Thread.currentThread().getName() 函數.

假如直接執行A.run()? 則返回的是當前線程(而不是A線程) 的名字,? 因為對象A并沒有啟動自己的線程.

假如執行難過A.start(), 那么該函數就返回A啟動的線程的名字了.



八, 小結

這篇文章只是簡介, 很多重要的方法例如 sleep() , wait() 等都沒有介紹, 這些是線程控制的內容. 本吊打算在另一篇博文里介紹.












總結

以上是生活随笔為你收集整理的Java 里的thread (线程)简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。