更新時間:2022-12-28 13:37:41 來源:動力節(jié)點 瀏覽1800次
通常,我們可以將線程定義為一個子進(jìn)程,它具有最小的進(jìn)程單元,是輕量級的,并且具有獨立的執(zhí)行路徑。這些線程使用共享內(nèi)存,但它們獨立運行,因此即使線程中存在異常也不會影響其他線程的工作,盡管它們共享相同的內(nèi)存。
正如我們在上圖中所觀察到的,一個線程在進(jìn)程內(nèi)部運行,線程之間將進(jìn)行基于上下文的切換,操作系統(tǒng)中可以運行多個進(jìn)程,每個進(jìn)程又可以同時運行多個線程。多線程概念廣泛應(yīng)用于游戲、動畫等領(lǐng)域。
為了幫助用戶操作系統(tǒng)為用戶提供了多任務(wù)處理的特權(quán),用戶可以在機器上同時執(zhí)行多個操作。可以通過兩種方式啟用此多任務(wù)處理:
基于進(jìn)程的多任務(wù)處理
基于線程的多任務(wù)處理
在這種類型的多任務(wù)處理中,進(jìn)程是重量級的,每個進(jìn)程都分配了一個單獨的內(nèi)存區(qū)域。并且由于進(jìn)程是重量級的,進(jìn)程之間的通信成本很高,進(jìn)程之間的切換需要很長時間,因為它涉及加載、保存到寄存器、更新映射、列表等操作。
正如我們上面所討論的,線程具有輕量級的特性,共享相同的地址空間,線程之間的通信成本也很低。
為什么使用線程?
現(xiàn)在,我們可以理解為什么要使用線程,因為它們具有輕量級的優(yōu)勢,并且可以以低成本提供多個線程之間的通信,從而有助于在共享內(nèi)存環(huán)境中進(jìn)行有效的多任務(wù)處理。
線程的生命周期
線程在其生命周期中會進(jìn)入不同的狀態(tài),讓我們通過以下幾行了解這些狀態(tài):在其生命周期中,線程會經(jīng)歷以下狀態(tài),即:
新州
活動狀態(tài)
等待/阻塞狀態(tài)
定時等待狀態(tài)
終止?fàn)顟B(tài)
我們可以在上圖中看到線程中不同狀態(tài)的工作,讓我們詳細(xì)了解每個狀態(tài):
(1)新狀態(tài)
默認(rèn)情況下,一個Thread會處于一個new狀態(tài),在這個狀態(tài)下,代碼還沒有運行,執(zhí)行過程還沒有啟動。
(2)活躍狀態(tài)
默認(rèn)情況下,處于新狀態(tài)的 Thread 在調(diào)用 start() 方法時會轉(zhuǎn)移到 Active 狀態(tài),他的 Active 狀態(tài)包含兩個子狀態(tài),即:
可運行狀態(tài):在此狀態(tài)下,線程已準(zhǔn)備好在任何給定時間運行,線程調(diào)度程序的工作是為可運行狀態(tài)保留的線程提供線程時間。已獲得多線程的程序共享在線程之間共享的時間間隔切片,因此,這些線程運行一段較短的時間跨度,并在可運行狀態(tài)下等待獲取它們的時間間隔調(diào)度切片。
Running State:當(dāng)Thread接收到Thread Scheduler分配的CPU時,從“Runnable”狀態(tài)轉(zhuǎn)為“Running”狀態(tài)。在其給定時間片會話期滿后,它再次回到“可運行”狀態(tài)并等待下一個時間片。
(3)等待/阻塞狀態(tài)
如果線程處于非活動狀態(tài)但處于臨時狀態(tài),則它處于等待或阻塞狀態(tài),例如,如果有兩個線程 T1 和 T2,其中 T1 需要與攝像頭通信,而其他線程 T2 已經(jīng)使用攝像頭進(jìn)行通信掃描然后T1等待直到T2線程完成它的工作,在這個狀態(tài)下T1停在等待狀態(tài),在另一種情況下,用戶調(diào)用了兩個具有相同功能的線程T2和T3,并且都具有線程調(diào)度程序給定的相同時間片那么線程 T1、T2 都處于阻塞狀態(tài)。當(dāng)有多個線程停在阻塞/等待狀態(tài)時,線程調(diào)度程序通過拒絕不需要的線程并按優(yōu)先級分配 CPU 來清除隊列。
(4)定時等待狀態(tài)
有時等待線程的較長持續(xù)時間會導(dǎo)致饑餓,如果我們舉個例子,比如有兩個線程 T1,T2 等待 CPU,并且 T1 正在進(jìn)行關(guān)鍵編碼操作,如果它在執(zhí)行操作之前不退出 CPU,那么 T2 將是暴露在不確定的情況下等待更長時間,為了避免這種饑餓情況,我們有 Timed Waiting 等待狀態(tài)以避免這種情況,因為在 Timed Waiting 中,每個線程都有一個調(diào)用 sleep() 方法的時間段,并且在時間到期,線程開始執(zhí)行其任務(wù)。
(5)終止?fàn)顟B(tài)
由于以下原因,線程將處于終止?fàn)顟B(tài):
正常情況下,線程在完成其任務(wù)時會終止。
有時,線程可能會由于異常事件(如分段錯誤、異常等)而終止。這種終止可以稱為異常終止。
終止的線程意味著它已經(jīng)死了并且不再可用。
正如我們所熟悉的,我們在每個 Java 程序中創(chuàng)建 Main 方法,它作為代碼由 JVM 執(zhí)行的入口點,同樣在這個多線程概念中,每個程序都有一個主線程,默認(rèn)情況下由JVM,因此無論何時在 Java 中創(chuàng)建程序,JVM 都會為其執(zhí)行提供主線程。
我們可以使用兩種方式在 java 中創(chuàng)建線程,即:
通過擴(kuò)展線程類
通過實現(xiàn) Runnable 接口
通過擴(kuò)展Thread類
我們可以使用 Thread 類在 Java 中運行線程,Thread 類提供構(gòu)造函數(shù)和方法來創(chuàng)建線程并在線程上執(zhí)行操作,線程擴(kuò)展了可以實現(xiàn) Runnable 接口的 Thread 類。我們使用以下構(gòu)造函數(shù)來創(chuàng)建線程:
線
線程(可運行 r)
線程(字符串名稱)
Thread(Runnable r, String name)
通過擴(kuò)展線程類創(chuàng)建線程的示例代碼:
import java.io.*;
import java.util.*;
public class GFG extends Thread {
// initiated run method for Thread
public void run()
{
System.out.println("Thread Started Running...");
}
public static void main(String[] args)
{
GFG g1 = new GFG();
// invoking Thread
g1.run();
}
}
輸出
線程開始運行...
使用 Runnable 接口創(chuàng)建線程的示例代碼:
import java.io.*;
import java.util.*;
public class GFG implements Runnable {
// method to start Thread
public void run()
{
System.out.println(
"Thread is Running Successfully");
}
public static void main(String[] args)
{
GFG g1 = new GFG();
// initializing Thread Object
Thread t1 = new Thread(g1);
t1.run();
}
}
輸出
線程運行成功
使用 Thread(String name) 在 Java 中創(chuàng)建線程的示例代碼:
import java.io.*;
import java.util.*;
public class GFG {
public static void main(String args[])
{
// Thread object created
// and initiated with data
Thread t = new Thread("Hello!");
// Thread gets started
t.start();
// getting data of
// Thread through String
String s = t.getName();
System.out.println(s);
}
}
輸出
你好!
使用 Thread(Runnable r, String name) 創(chuàng)建線程對象的示例 Java 代碼:
import java.io.*;
import java.util.*;
public class GFG implements Runnable {
public void run()
{
System.out.println(
"Thread is created and running successfully...");
}
public static void main(String[] args)
{
// aligning GFG Class with
// Runnable interface
Runnable r1 = new GFG();
Thread t1 = new Thread(r1, "My Thread");
// Thread object started
t1.run();
// getting the Thread
// with String Method
String str = t1.getName();
System.out.println(str);
}
}
輸出
線程已創(chuàng)建并成功運行...
我的線程
探索不同線程狀態(tài)的 Java 程序:
讓我們通過在線程 t1 和 t2 上實現(xiàn)它們來了解線程狀態(tài)的工作原理。
輸出:
import java.io.*;
import java.util.*;
class GFG implements Runnable {
public void run()
{
// implementing try-catch Block to set sleep state
// for inactive thread
try {
Thread.sleep(102);
}
catch (InterruptedException i1) {
i1.printStackTrace();
}
System.out.println(
"The state for t1 after it invoked join method() on thread t2"
+ " " + ThreadState.t1.getState());
// implementing try-catch block
try {
Thread.sleep(202);
}
catch (InterruptedException i2) {
i2.printStackTrace();
}
}
}
// creation of ThreadState class
// to implement Runnable interface
public class ThreadState implements Runnable {
public static Thread t1;
public static ThreadState o1;
public static void main(String args[])
{
o1 = new ThreadState();
t1 = new Thread(o1);
System.out.println("post-spanning, state of t1 is"
+ " " + t1.getState());
// lets invoke start() method on t1
t1.start();
// Now,Thread t1 is moved to runnable state
System.out.println(
"post invoking of start() method, state of t1 is"
+ " " + t1.getState());
}
public void run()
{
GFG g1 = new GFG();
Thread t2 = new Thread(g1);
// Thread is created and its in new state.
t2.start();
// Now t2 is moved to runnable state
System.out.println(
"state of t2 Thread, post-calling of start() method is"
+ " " + t2.getState());
// create a try-catch block to set t1 in waiting
// state
try {
Thread.sleep(202);
}
catch (InterruptedException i2) {
i2.printStackTrace();
}
System.out.println(
"State of Thread t2 after invoking to method sleep() is"
+ " " + t2.getState());
try {
t2.join();
System.out.println(
"State of Thread t2 after join() is"
+ " " + t2.getState());
}
catch (InterruptedException i3) {
i3.printStackTrace();
}
System.out.println(
"state of Thread t1 after completing the execution is"
+ " " + t1.getState());
}
}
輸出
后跨越,t1 的狀態(tài)是新的
調(diào)用 start() 方法后,t1 的狀態(tài)為 RUNNABLE
t2 線程的狀態(tài),調(diào)用 start() 方法后為 RUNNABLE
t1 在線程 t2 上調(diào)用 join method() 后的狀態(tài) TIMED_WAITING
調(diào)用方法 sleep() 后線程 t2 的狀態(tài)為 TIMED_WAITING
join() 終止后線程 t2 的狀態(tài)
執(zhí)行完成后線程 t1 的狀態(tài)為 RUNNABLE
以上就是關(guān)于“Java線程詳解”的介紹,大家如果想了解更多相關(guān)知識,不妨來關(guān)注一下本站的Java在線學(xué)習(xí),里面的課程內(nèi)容細(xì)致全面,很適合沒有基礎(chǔ)的小伙伴學(xué)習(xí),希望對大家能夠有所幫助。