国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~

這篇具有很好參考價值的文章主要介紹了【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

??本節(jié)學習目標

  • 理解進程與線程的區(qū)別;
  • 掌握Java 中多線程的兩種實現(xiàn)方式及區(qū)別;
  • 掌握線程的基本操作方法;

1?? 線程與進程

進程是程序的一次動態(tài)執(zhí)行過程,它經(jīng)歷了從代碼加載、執(zhí)行到執(zhí)行完畢的一個完整過程,這個過程也是進程本身從產(chǎn)生、發(fā)展到最終消亡的過程。多進程操作系統(tǒng)能同時運行多個進程(程序), 由于CPU具備分時機制,所以每個進程都能循環(huán)獲得自己的 CPU 時間片。由于 CPU 執(zhí)行速度非??欤沟盟谐绦蚝孟袷窃?“同時” 運行一樣。

線程和進程一樣,都是實現(xiàn)并發(fā)的一個基本單位。線程是比進程更小的執(zhí)行單位,線程是在進程的基礎(chǔ)之上進行的進一步劃分。多線程是實現(xiàn)并發(fā)機制的一種有效手段。所謂多線程是指一個進程在執(zhí)行過程中可以產(chǎn)生多個線程,這些線程可以同時存在、同時運行。 一個進程可能包含多個同時執(zhí)行的線程,如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

所有的線程一定要依附于進程才能夠存在,那么進程一旦消失了,線程也一定會消失。而 Java 是為數(shù)不多的支持多線程的開發(fā)語言之一。

??關(guān)于多進程、多線程、并發(fā)與并行之間的概念關(guān)系?

多進程、多線程、并發(fā)與并行是計算機領(lǐng)域中常用的術(shù)語,它們描述了不同的程序執(zhí)行方式和任務(wù)處理方式。

多進程(Multiprocessing):多進程指的是在操作系統(tǒng)層面上同時運行多個獨立的進程。每個進程都有自己的內(nèi)存空間和系統(tǒng)資源,并且通過進程間通信(IPC)來實現(xiàn)數(shù)據(jù)的交換和共享。多進程能夠使得多個任務(wù)并行執(zhí)行,每個進程分別處理自己的任務(wù),互不干擾。多進程適合于利用多核或分布式系統(tǒng)來提高整體系統(tǒng)的吞吐量和處理能力。

多線程(Multithreading):多線程指的是在單個進程內(nèi)部創(chuàng)建多個輕量級的執(zhí)行單位(線程)。這些線程共享進程的內(nèi)存空間和系統(tǒng)資源,可以方便快速地進行通信和共享數(shù)據(jù)。不同線程之間可以并發(fā)地執(zhí)行不同的任務(wù),有效利用了多核處理器的優(yōu)勢。多線程適用于需要同時處理多個任務(wù)、要求高響應(yīng)性和資源共享的場景。

并發(fā)(Concurrency):并發(fā)指的是多個任務(wù)在時間上交替執(zhí)行。在并發(fā)編程中,任務(wù)可能按照任意順序進行切換,通過時間片輪轉(zhuǎn)等技術(shù)來平衡任務(wù)的執(zhí)行。并發(fā)編程關(guān)注的是任務(wù)之間對共享資源的正確訪問和同步,以避免競態(tài)條件等問題。

并行(Parallelism):并行指的是將一個大任務(wù)劃分成多個子任務(wù),并且同時執(zhí)行這些子任務(wù),從而加速整體任務(wù)的完成速度。并行編程利用了多核處理器或者分布式系統(tǒng)的能力來實現(xiàn)任務(wù)的同時執(zhí)行,提高了整體計算能力。在并行編程中,需要考慮數(shù)據(jù)共享與通信的問題以及正確處理并行任務(wù)的調(diào)度和負載均衡。

簡而言之,多進程與多線程都可以實現(xiàn)并發(fā)的效果,但多進程是通過同時運行不同的進程,在操作系統(tǒng)層面上進行并行處理;而多線程是在單個進程內(nèi)部運行多個線程,通過在用戶空間內(nèi)進行并發(fā)執(zhí)行。并發(fā)指的是多個任務(wù)按照某種順序快速交替執(zhí)行,而并行指的是同時執(zhí)行多個任務(wù)以提升整體性能。

2?? 多線程實現(xiàn)

在 Java 中,如果要想實現(xiàn)多線程的程序,就必須依靠一個線程的主體類(就好比主類的概念一樣, 表示的是一個線程的主類)。但是這個線程的主體類在定義時也需要有一些特殊的要求,即此類需要繼承 Thread 類或?qū)崿F(xiàn) Runnable(Callable) 接口來完成定義。

JDK從最早開始定義多線程支持時,只有兩種實現(xiàn)要求:要么繼承Thread類,要么實現(xiàn) Runnable 接口,而在JDK 1.5開始又提供了一個新的線程接口:Callable。

從實際的開發(fā)角度而言,很明顯,使用接口定義的線程類會更加合理,因為使用繼承 Thread類的方式實現(xiàn)會帶來單繼承局限。

2.1 繼承 Thread 類

java.lang.Thread 是一個負責線程操作的類,任何類只需要繼承 Thread 類就可以成為一個線程的主類。但是既然是主類就必須有它的使用方法,而線程啟動的 主方法需要覆寫 Thread 類中的 run()方法實現(xiàn),線程主體類的定義格式如下。

class 類名稱 extends Thread{		//繼承Thread類
	屬性… ;	//類中定義屬性
	方法… ;	//類中定義方法
	public void run(){	//覆寫Thread類中的run0方法,此方法是線程的主體
		...
	}
}
//	范例 1: 定義一個線程操作類
class MyThread extends Thread {	//這就是一個多線程的操作類
	private String name;	//定義類中的屬性
	
	public MyThread(String name){	//定義構(gòu)造方法
		this.name = name;
	}

	@Override
	public void run(){		//覆寫run()方法,作為線程的主操作方法
		for (int x=0; x<5; x++){
			System.out.println(this.name + "-->" + x);
		}
	}
}

此程序線程類的功能是進行循環(huán)的輸出操作,所有的線程與進程是一樣的,都必須輪流去搶占資源,所以多線程的執(zhí)行應(yīng)該是多個線程彼此交替執(zhí)行。也就是說,如果直接調(diào)用 run()方法,并不能啟動多線程,多線程啟動的唯一方法就是 Thread 類中的 start()方法:

public void start();

調(diào)用此方法時,執(zhí)行的方法體是 run() 方法定義的代碼。

//	范例 2: 啟動多線程
public class TestDemo{                                                              //主類
	public static void main(String[] args){
		MyThread mt1 = new MyThread("線程A"); 	// 實例化多線程類對象
		MyThread mt2 = new MyThread("線程B");	// 實例化多線程類對象
		MyThread mt3 = new MyThread("線程C");	// 實例化多線程類對象
		mt1.start();  	//啟動多線程
		mt2.start(); 
		mt3.start();
	}
}

程序執(zhí)行結(jié)果:

線程B-->0
線程A-->0
線程A-->1
線程C-->0
線程C-->1
線程A-->2
線程B-->1
線程B-->2
線程B-->3
線程A-->3
線程C-->2
線程A-->4
線程B-->4
線程C-->3
線程C-->4

程序首先實例化了3個線程類對象,然后調(diào)用了通過 Thread 類繼承而來的 start()方法,進行多線程的啟動。通過本程序可以發(fā)現(xiàn)所有的線程都是交替運行的。

在范例中使用了 Thread類繼承的 start()方法啟動多線程,但是最終調(diào)用的依然是 run() 方法定義的代碼,那么為什么要這么做?為什么不直接調(diào)用 run()呢 ?

原因是多線程的操作是需要操作系統(tǒng)支持。為了解釋多線程啟動調(diào)用的問題,下面可以打開 java.lang.Thread 類的 start()源代碼來進行觀察。

//	范例 3: start()方法的源代碼
public synchronized void start(){
	if (threadStatus != 0)
		throw new IllegalThreadStateException();
	group.add(this);
	boolean started = false;
	try {
		start0();
		started = true;
	} finally {
		try {
			if(!started){
				group.threadStartFailed(this);
			}
		} catch (Throwable ignore){
		}
	}
}
private native void start0();

通過程序可以發(fā)現(xiàn)在 start() 方法里面要調(diào)用一個 start0()方法,而且此方法的結(jié)構(gòu)與抽象方法類似,使用了native聲明。在Java的開發(fā)里面有一門技術(shù)稱為Java本地接口 (Java Native Interface, JNI) 技術(shù),這門技術(shù)的特點是使用Java調(diào)用本機操作系統(tǒng)提供的函數(shù)。但是此技術(shù)有一個缺點,不能離開特定的操作系統(tǒng)。如果要想能夠執(zhí)行線程,需要操作系統(tǒng)來進行資源分配,所以此操作嚴格來講主要是由JVM負責根據(jù)不同的操作系統(tǒng)而實現(xiàn)的。即是說使用Thread 類的 start0()方法不僅要啟動多線程的執(zhí)行代碼,還要根據(jù)不同的操作系統(tǒng)進行資源的分配。

另外需要注意的是,可以發(fā)現(xiàn)在 Thread類的 start()方法里面存在一個"IlegalThreadStateException"異常拋出。本方法里面使用了throw拋出異常,照道理講應(yīng)該使用 try..catch處理,或者在 start() 方法聲明上使用 throws聲明,但是此處并未這樣處理,

原因是在IlegalThreadStateException異常類繼承結(jié)構(gòu)中,可以發(fā)現(xiàn)此異常屬于 RuntimeException 的子類,這樣就可以由用戶選擇性進行處理。如果某一個線程對象重復(fù)進行了啟動 ( 同一個線程對象調(diào)用多次start()方法),就會拋出此異常。

2.2 實現(xiàn) Runnable 接口

使用 Thread 類的確可以方便地進行多線程的實現(xiàn),但是這種方式最大的缺點就是單繼承的問題,為此,在 Java 中也可以利用 Runnable接口來實現(xiàn)多線程,而這個接口的定義如下。

@Functionallnterface
public interface Runnable{
	public void run();
}

Runnable 接口中也定義了 run() 方法,所以線程的主類只需要覆寫此方法即可。

//	范例 4: 使用 Runnable 實現(xiàn)多線程
class MyThread implements Runnable {               //定義線程主體類
	private String name;                        	//定義類中的屬性
	
	public MyThread(String name){                         //定義構(gòu)造方法
		this.name = name;
	}
	
	@Override
	public void run(){                        	//覆寫run()方法
		for (int x=0; x<5; x++){
			System.out.println(this.name + "-->" + x);
		}
	}
}

此程序?qū)崿F(xiàn)了 Runnable 接口并且正常覆寫了 run()方法,但是卻會存在一個新的問題:要啟動多線程, 一定需要通過 Thread 類中的 start() 方法才可以完成。如果繼承了 Thread 類,那么可以直接將 Thread 父類中的 start() 方法繼承下來繼續(xù)使用,而 Runnable 接口并沒有提供可以被繼承的 start()方法,這時該如何啟動多線程呢?

此時可以觀察 Thread 類中提供的一個有參構(gòu)造方法:

public Thread(Runnable target);

此方法可以接收一個 Runnable 接口對象。

//	范例 5: 利用Thread 類啟動多線程
public class TestDemo {
	public static void main(String[] args){
		MyThread mt1 = new MyThread("線程A");	// 實例化多線程類對象
		MyThread mt2 = new MyThread("線程B"); 
		MyThread mt3 = new MyThread("線程C"); 
		new Thread(mt1).start();		//利用Thread 啟動多線程
		new Thread(mt2).start();
		new Thread(mt3).start();
	}
}

程序執(zhí)行結(jié)果:

線程A-->0
線程B-->0
線程C-->0
線程B-->1
線程A-->1
線程B-->2
線程C-->1
線程B-->3
線程B-->4
線程A-->2
線程C-->2
線程A-->3
線程C-->3
線程C-->4
線程A-->4

此程序首先利用 Thread 類的對象包裝了 Runnable 接口對象實例 (new Thread(mt1).start()), 然后利用 Thread 類的 start() 方法就可以實現(xiàn)多線程的啟動。

可以發(fā)現(xiàn),在 Runnable 接口聲明處使用了“@FunctionalInterface”的 注解,證明Runnable是一個函數(shù)式接口,所以對于范例5的操作也可以使用 Lambda 表達式的風格簡化編寫。

//	范例 6: 使用Lambda表達式實現(xiàn)多線程
public class TestDemo {
public static void main(String[] args){
	String name ="線程對象";
	new Thread(() -> {
		for (int x=0; x<5; x++){
			System.out.println(name + "-->" + x);
	}).start();
}

此程序利用 Lambda表達式直接定義的線程主體實現(xiàn)操作,并且依然依靠 Thread 類的 start() 方法進行啟動,這樣的做法要比直接使用Runnable 接口的匿名內(nèi)部類更加方便。

使用 Runnable接口可以有效避免單繼承局限問題,所以在實際的開發(fā)中,對于多線程的實現(xiàn)首先選擇的就是 Runnable 接口。

2.3 多線程兩種實現(xiàn)方式的區(qū)別

Thread 類 和 Runnable 接口都可以作為同一功能的方式來實現(xiàn)多線程,但從 Java 的實際開發(fā)角度來講,肯定使用 Runnable 接口,因為它可以有效避免單繼承的局限。那么除了這些,這兩種方式是否還有其他聯(lián)系呢?

為了解釋這兩種方式的聯(lián)系,下面可以觀察 Thread 類的定義。

public class Thread extends Object implements Runnable	...	

通過定義可以發(fā)現(xiàn) Thread 類也是 Runnable 接口的子類,這樣對于之前利用 Runnable 接口實現(xiàn)的多線程,其類圖結(jié)構(gòu)如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端
上圖所表現(xiàn)出來的代碼設(shè)計模式非常類似于代理設(shè)計模式,但是它并不是嚴格意義上的代理設(shè)計模式,因為嚴格來講代理設(shè)計模式中,代理主題能夠使用的方法依然是接口中定義的 run ()方法,而此處代理主題調(diào)用的是 start() 方法,所以只能說形式上類似于代理設(shè)計模式,但本質(zhì)上還是有差別的。

除了以上聯(lián)系外,對于 Runnable 接口和 Thread 類還有一個不太好區(qū)分的特點:使用 Runnable 接口可以更加方便地表示出數(shù)據(jù)共享的概念。

//	范例 7: 通過繼承 Thread 類實現(xiàn)賣票程序
package com.xiaoshan.demo;

class MyThread extends Thread  {	//線程的主體類 
	private int ticket = 5;		//一共5張票
	
	@Override
	public void run(){		//線程的主方法
		for (int x=0; x<50; x++){	 //循環(huán)50次
			if (this.ticket >0){
				System.out.println("賣票, ticket ="+ this.ticket--);
			}
		}
	}
}

public class TestDemo{
	public static void main(String[] args) throws Exception {
		MyThread mtl = new  MyThread(); 	//創(chuàng)建線程對象
		MyThread mt2 = new  MyThread(); 
		MyThread mt3 = new  MyThread(); 
		mtl.start();		//啟動線程
		mt2.start();	
		mt3.start();
	}
}

程序執(zhí)行結(jié)果:

賣票, ticket =5
賣票, ticket =4
賣票, ticket =5
賣票, ticket =4
賣票, ticket =3
賣票, ticket =2
賣票, ticket =5
賣票, ticket =1
賣票, ticket =3
賣票, ticket =2
賣票, ticket =1
賣票, ticket =4
賣票, ticket =3
賣票, ticket =2
賣票, ticket =1

此程序定義了3個線程對象,希望3個線程對象同時賣5張車票,而最終的結(jié)果是一共買出了15張票,等于每一個線程對象各自賣各自的5張票,這時的內(nèi)存關(guān)系如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

而下面我們使用第二種實現(xiàn) Runnable接口的方式來實現(xiàn)此功能:

//	范例 8: 利用Runnable 接口來實現(xiàn)多線程
package com.xiaoshan.demo;

class MyThread implements Runnable { 	//線程的主體類
	private int ticket =5;	//一共5張票
	
	@Override
	public void run(){	//線程的主方法
		for (int x=0; x<50; x++){	//循環(huán)50次
			if (this.ticket>0){
				System.out.println("賣票,ticket="+ this.ticket--);
			}
		}
	}
}

public class TestDemo  {
	public static void main(String[] args) throws Exception {
		MyThread mt = new MyThread();                 //創(chuàng)建線程對象
		new Thread(mt).start();          	//啟動線程
		new Thread(mt).start();            
		new Thread(mt).start();
	}
}                                

程序執(zhí)行結(jié)果:

賣票,ticket=5
賣票,ticket=3
賣票,ticket=4
賣票,ticket=1
賣票,ticket=2

此程序使用 Runnable 實現(xiàn)了多線程,同時啟動了3個線程對象,但是與使用 Thread 操作的賣票范例不同的是,這3個線程對象都占著同一個 Runnable 接口對象的引用,所以實現(xiàn)了數(shù)據(jù)共享的操作。 程序的內(nèi)存關(guān)系如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

綜上,多線程的繼承Thread類、實現(xiàn)Runnable接口 兩種實現(xiàn)方式的區(qū)別是:

  • 都需要一個線程的主類,而這個類可以實現(xiàn) Runnable 接口或繼承 Thread 類,不管使用何種方式都必須在子類中覆寫 run()方法,此方法為線程的主方法;
  • Thread 類是 Runnable 接口的子類,而且使用 Runnable 接口可以避免單繼承局限,并且可以更加方便地實現(xiàn)數(shù)據(jù)共享的概念。

2.4 利用 Callable 接口實現(xiàn)多線程

使用 Runnable 接口實現(xiàn)的多線程可以避免單繼承局限,但是 Runnable 接口實現(xiàn)的多線程會存在一個問題: Runnable 接口里面的 run()方法不能返回操作結(jié)果。 所以為了解決這樣的問題,從 JDK1.5 開始,Java 對于多線程的實現(xiàn)提供了一個新的接口: java.util.concurrent.Callable,此接口定義如下。

@Functionallnterface
public interface Callable<V>{
	public V call() throws Exception;
}

在接口中存在一個 call()方法,而在 call()方法上可以實現(xiàn)線程操作數(shù)據(jù)的返回,而返回的數(shù)據(jù)類型由Callable 接口上的泛型類型動態(tài)決定。

//	范例 9: 定義一個線程主體類
import java.util.concurrent.Callable;

class MyThread implements Callable<String>{              //多線程主體類
	private int ticket = 5;              //賣票
	
	@Override
	public String call() throws Exception{
		for (int x=0; x<100; x++){
			if (this.ticket >0){            	//還有票可以出售
				System.out.println("賣票,ticket=" + this.ticket--);
			}
		}
		return "票已賣光!";
	}
}

此程序中定義的 call() 方法在操作完成后可以直接返回一個具體的操作數(shù)據(jù),本次返回的是一個 String 型數(shù)據(jù)。

當多線程的主體類定義完成后,要利用 Thread 類啟動多線程,但是在 Thread 類中并沒有定義任何構(gòu)造方法可以直接接收 Callable 接口對象實例,并且由于需要接收 call()方法返回值的問題,從 JDK1.5開始, Java 提供了一個 java.util.concurrent.FutureTask<V> 類,此類定義如下。

public class FutureTask<V> extends Object implements RunnableFuture<V> ...

通過定義可以發(fā)現(xiàn)此類實現(xiàn)了 RunnableFuture 接口,而 RunnableFuture 接口又同時實現(xiàn)了 FutureRunnable 接口。FutureTask 類繼承結(jié)構(gòu)如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端
清楚了 FutureTask 類的繼承結(jié)構(gòu)之后,下面再來研究 FutureTask 類的常用方法,方法聲明、方法類型及描述如下所示:

  • public FutureTask(Callable<V> callable):構(gòu)造方法,接收Callable接口實例;
  • public FutureTask(Runnable runnable, V result):構(gòu)造方法,接收Runnable接口實例,并指定返回結(jié)果類型;
  • public V get() throws InterruptedException, ExecutionException:普通方法,取得線程操作結(jié)果,此方法為 Future 接口定義。

通過 FutureTask 類繼承結(jié)構(gòu)可以發(fā)現(xiàn)它是 Runnable 接口的子類,并且 FutureTask 類可以接收 Callable 接口實例,這樣依然可以利用Thread 類來實現(xiàn)多線程的啟動,而如果要想接收返回結(jié)果,利用 Future 接口中的 get() 方法即可。

//	范例 10: 啟動多線程
import java.util.concurrent.FutureTask;

public class TestDemo {
	public static void main(String[] args) throws Exception{
		MyThread mt1 = new MyThread();  // 實例化多線程對象
		MyThread mt2 = new MyThread(); // 實例化多線程對象
		FutureTask<String> task1 = new FutureTask<String>(mt1);
		FutureTask<String> task2 = new FutureTask<String>(mt2);
		
		// FutureTask是 Runnable接口子類,所以可以使用Thread類的構(gòu)造來接收task對象
		new Thread(task1).start();              //啟動第一個線程
		new Thread(task2).start();               //啟動第二個線程
		//多線程執(zhí)行完畢后可以取得內(nèi)容,依靠FutureTask的父接口Future中的get()方法實現(xiàn) 
		System.out.println("A線程的返回結(jié)果:"+ task1.get());
		System.out.println("B線程的返回結(jié)果:"+ task2.get());
	}
}

程序執(zhí)行結(jié)果:

賣票,ticket=5
賣票,ticket=5
賣票,ticket=4
賣票,ticket=4
賣票,ticket=3
賣票,ticket=3
賣票,ticket=2
賣票,ticket=2
賣票,ticket=1
賣票,ticket=1
A線程的返回結(jié)果:票已賣光!
B線程的返回結(jié)果:票已賣光!

此程序利用 FutureTask 類實現(xiàn) Callable 接口的子類包裝,由于 FutureTaskRunnable 接口的子類,所以可以利用 Thread 類的 start()方法啟動多線程,當線程執(zhí)行完畢后,可以利用 Future 接口中的 get() 方法返回線程的執(zhí)行結(jié)果。

通過 Callable接口與 Runnable 接口實現(xiàn)的比較,可以發(fā)現(xiàn),Callable接口只是勝在有返回值上。但是Runnable接口是Java最早提供的,也是使用最廣泛的接口,所以在進行多線程實現(xiàn)時還是建議優(yōu)先考慮使用 Runnable 接口。

2.5 線程的狀態(tài)

要想實現(xiàn)多線程,必須在主線程中創(chuàng)建新的線程對象。任何線程一般都具有5種狀態(tài),即創(chuàng)建、就緒、運行、阻塞和銷毀。線程轉(zhuǎn)換狀態(tài)如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

  1. 創(chuàng)建狀態(tài)
    在程序中用構(gòu)造方法創(chuàng)建一個線程對象后,新的線程對象便處于新建狀態(tài),此時,它已經(jīng)有相應(yīng)的內(nèi)存空間和其他資源,但還處于不可運行狀態(tài)。新建一個線程對象可采用 Thread 類的構(gòu)造方法來實現(xiàn),例如: Thread thread=new Thread()。
  2. 就緒狀態(tài)
    新建線程對象后,調(diào)用該線程的 start()方法就可以啟動線程。當線程啟動時,線程進入就緒狀態(tài)。 此時,線程將進入線程隊列排隊,等待CPU 服務(wù),這表明它已經(jīng)具備了運行條件。
  3. 運行狀態(tài)
    當就緒狀態(tài)的線程被CPU調(diào)用并獲得處理器資源時,線程就進入了運行狀態(tài)。此時,自動調(diào)用該線程對象的 run()方法。 run() 方法定義了該線程的操作和功能。
  4. 阻塞狀態(tài)
    一個正在執(zhí)行的線程在某些特殊情況下,如被人為掛起或需要執(zhí)行耗時的輸入輸出操作時,將讓出 CPU 并暫時中止自己的執(zhí)行,進入阻塞狀態(tài)。在可執(zhí)行狀態(tài)下,如果調(diào)用 sleep()suspend()、wait() 等方法,線程都將進入阻塞狀態(tài)。阻塞時,線程不能進入排隊隊列,只有當引起阻塞的原因被消除后,線程才可以轉(zhuǎn)入就緒狀態(tài)。
  5. 銷毀/終止狀態(tài)
    線程調(diào)用 stop() 方法時或 run()方法執(zhí)行結(jié)束后,就處于終止狀態(tài)。處于終止狀態(tài)的線程不具有繼續(xù)運行的能力。

3?? 多線程常用操作方法

Java 除了支持多線程的定義外,也提供了許多多線程操作方法,其中大部分方法都是在 Thread 類中定義的,下面介紹3個主要方法的使用。

3.1 線程的命名與取得

所有線程程序的執(zhí)行,每一次都是不同的運行結(jié)果,因為它會根據(jù)自己的情況進行資源搶占,所以要想?yún)^(qū)分每一個線程,就必須依靠線程的名字。對于線程名字一般而言會在其啟動之前進行定義,不建議對已經(jīng)啟動的線程更改名稱,或者是為不同的線程設(shè)置重名的情況。
如果要想進行線程命名的操作,可以使用 Thread 類的方法,方法聲明及描述如下所示:

  • public Thread(Runnable target, String name):構(gòu)造方法,實例化線程對象,接收 Runnable接口子類對象,同時設(shè)置線程名稱;
  • public final void setName(String name):普通方法,設(shè)置線程名字;
  • public final String getName():普通方法,取得線程名字。

由于多線程的狀態(tài)不確定,所以線程的名字就成為了唯一的分辨標記,則在定義線程名稱時一定要在線程啟動前設(shè)置名字,而盡量不要重名,且量不要為已經(jīng)啟動的線程修改名字。

由于線程的狀態(tài)不確定,所以每次可以操作的都是正在執(zhí)行 run()方法的線程,那么取得當前線程對象的方法為:

public static Thread currentThread();
//	范例 11: 觀察線程的命名
package com.xiaoshan.demo;

class MyThread implements Runnable{
	@Override
	public void run(){
		System.out.println(Thread.currentThread().getName());
	}
}

public class TestDemo {
	public static void main(String[] args) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt,"自己的線程A").start();
		new Thread(mt).start();
		new Thread(mt,"自己的線程B").start();
		new Thread(mt).start();
		new Thread(mt).start();
	}
}

執(zhí)行結(jié)果:

自己的線程A
Thread-2
Thread-1
自己的線程B
Thread-0

通過程序可以發(fā)現(xiàn),當實例化 Thread 類對象時可以自己定義線程名稱,也可以采用默認名稱進行操作。在 run() 方法中可以使用 currentThread() 取得當前線程對象后再取得具體的線程名字。

//	范例 12: 取得線程名字
package com.xiaoshan.demo;

class MyThread implements Runnable{
	@Override
	public void run(){
		System.out.println(Thread.currentThread().getName());
	}
}

public class TestDemo{
	public static void main(String[] args) throws Exception{
		MyThread mt = new MyThread();
		new Thread(mt,"自己的線程對象").start();
		mt.run();                       //直接調(diào)用run()方法,main
	}
}

可能的執(zhí)行結(jié)果:

main
自己的線程對象

此程序首先實例化了 Thread 類對象,然后利用多線程啟動 start()間接調(diào)用了 run() 方法,同時又在主類中直接利用對象調(diào)用了 MyThread 類中的 run() 方法,這樣就可以發(fā)現(xiàn)主方法本身也屬于一個線程。

3.2 線程的休眠

線程的休眠指的是讓程序的執(zhí)行速度變慢一些,在 Thread 類中線程休眠操作方法為:

public static void sleep(long millis) throws InterruptedException

方法設(shè)置的休眠時間單位是毫秒 (ms)。

//	范例 13: 觀察休眠特點
package com.xiaoshan.demo;

class MyThread implements Runnable{
	@Override
	public void run(){
		for (int x=0; x<5; x++){
			try{
				Thread.sleep(1000);	//每次執(zhí)行休眠1s
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + ", x="+x);
		}
	}
}

public class TestDemo{
	public static void main(String[] args) throws Exception{
		MyThread mt = new MyThread();
		new Thread(mt,"自己的線程對象A").start();
	}
}

可能的執(zhí)行結(jié)果:

自己的線程對象A, x=0
自己的線程對象A, x=1
自己的線程對象A, x=2
自己的線程對象A, x=3
自己的線程對象A, x=4

此程序在每一次線程執(zhí)行 run() 方法時都會產(chǎn)生1s 左右的延遲后才會進行內(nèi)容的輸出,所以整體代碼執(zhí)行速度有所降低。

3.3 線程優(yōu)先級

在 Java 的線程操作中,所有的線程在運行前都會保持就緒狀態(tài),此時哪個線程的優(yōu)先級高,哪個線程就有可能會先被執(zhí)行。線程的優(yōu)先級如下圖所示。

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

如果要想進行線程優(yōu)先級的設(shè)置,在 Thread 類中提供了支持的方法及常量,如下所示:

  • public static final int MAX_PRIORITY:常量,最高優(yōu)先級,數(shù)值為10;
  • public static final int NORM_PRIORITY:常量,中等優(yōu)先級,數(shù)值為5;
  • public static final int MIN_PRIORITY:常量,最低優(yōu)先級,數(shù)值為1;
  • public final void setPriority(int newPriority):普通方法,設(shè)置線程優(yōu)先級;
  • public final int getPriority():普通方法,取得線程優(yōu)先級。
//	范例 14: 設(shè)置線程優(yōu)先級
package com.xiaoshan.demo;

class MyThread implements Runnable {
	@Override
	public void run(){
		for (int x=0; x<5; x++){
			try{
				Thread.sleep(100);
			}catch (InterruptedException e){
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+",x="+x);
		}
	}
}

public class TestDemo{
	public static void main(String[] args) throws Exception {
		MyThread mt = new MyThread();
		Thread t1 = new Thread(mt,"自己的線程對象A");
		Thread t2 = new Thread(mt,"自己的線程對象B");
		Thread t3 = new Thread(mt,"自己的線程對象C");
		t3.setPriority(Thread.MAX_PRIORITY);                  //修改一個線程對象的優(yōu)先級
		t1.start();
		t2.start();
		t3.start();
	}
}

執(zhí)行結(jié)果:

自己的線程對象C,x=0
自己的線程對象A,x=0
自己的線程對象B,x=0
自己的線程對象C,x=1
自己的線程對象A,x=1
自己的線程對象B,x=1
自己的線程對象A,x=2
自己的線程對象B,x=2
自己的線程對象C,x=2
自己的線程對象B,x=3
自己的線程對象A,x=3
自己的線程對象C,x=3
自己的線程對象B,x=4
自己的線程對象C,x=4
自己的線程對象A,x=4

此程序定義了3個線程對象,并在線程對象啟動前,利用 setPriority() 方法修改了一個線程的優(yōu)先級。

3.4 線程等待

join()方法允許一個線程等待另一個線程執(zhí)行完成。調(diào)用join()方法的線程將會阻塞,直到被調(diào)用的線程執(zhí)行完畢。通過使用join()方法,可以保證線程之間的協(xié)作和順序執(zhí)行。

下面是一個示例代碼:

//	范例 15: join()方法的作用
package com.xiaoshan.demo;

class MyRunnable implements Runnable {
	@Override
	public void run() {
    	System.out.println(Thread.currentThread().getName() + " started");
        try {
        	Thread.sleep(2000);
        } catch (InterruptedException e) {
        	System.out.println(Thread.currentThread().getName() + " interrupted");
       	}
        System.out.println(Thread.currentThread().getName() + " completed");
  	}
}
    
public class JoinExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new MyRunnable(), "Thread 1");
        Thread thread2 = new Thread(new MyRunnable(), "Thread 2");
        
        thread1.start();
        try {
            // 在主線程中等待thread1執(zhí)行完成
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println("Thread 1 interrupted");
        }
        
        thread2.start();
    }
}

執(zhí)行結(jié)果:

Thread 1 started
Thread 1 completed
Thread 2 started
Thread 2 completed

在上述代碼中,創(chuàng)建了兩個線程:thread1thread2。調(diào)用thread1.join()方法使得主線程等待thread1執(zhí)行完畢再繼續(xù)執(zhí)行。這樣可以確保thread2thread1執(zhí)行完成后再開始執(zhí)行。

通過調(diào)用join()方法,我們可以確保線程的順序執(zhí)行。在以上示例中,主線程調(diào)用了thread1.join()方法等待thread1完成,所以在輸出結(jié)果中可以看到thread1的執(zhí)行先于thread2。

這說明了join()方法的作用是使得一個線程等待其他線程執(zhí)行完成,從而實現(xiàn)線程間的協(xié)作和順序執(zhí)行。在需要確保某個線程執(zhí)行完畢后再進行下一步操作時,可以使用join()方法來實現(xiàn)。

3.5 線程讓出執(zhí)行權(quán)

yield()方法允許當前線程讓出CPU的執(zhí)行時間,給其他具有相同優(yōu)先級的線程執(zhí)行的機會。調(diào)用yield()方法后,當前線程將進入就緒狀態(tài),重新參與調(diào)度。注意,yield()方法只是提供一種暗示,不能保證被立即執(zhí)行。

下面是一個示例代碼:

//	范例 16: yield()方法的作用
package com.xiaoshan.demo;

class MyRunnable implements Runnable {
	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			System.out.println(Thread.currentThread().getName() + ": " + i);
			// 當i為3時,讓出CPU執(zhí)行時間
			if(i == 3){
				Thread.yield();
			}
		}
	}
}

public class YieldExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new MyRunnable(), "Thread 1");
        Thread thread2 = new Thread(new MyRunnable(), "Thread 2");
        
        thread1.start();
        thread2.start();
    }
}

輸出結(jié)果:

Thread 1: 1
Thread 1: 2
Thread 1: 3
Thread 2: 1
Thread 2: 2
Thread 2: 3
Thread 1: 4
Thread 1: 5
Thread 2: 4
Thread 2: 5

在上述代碼中,創(chuàng)建了兩個線程:thread1thread2。在每個線程的執(zhí)行過程中,當循環(huán)變量i等于3時,調(diào)用Thread.yield()方法讓出CPU執(zhí)行時間。這樣可以使得兩個線程之間更平衡地共享CPU資源。

通過調(diào)用yield()方法,我們可以讓線程主動讓出CPU執(zhí)行時間。在以上示例中,當thread1thread2的循環(huán)變量i等于3時,它們分別調(diào)用了Thread.yield()方法,從而使得兩個線程交替執(zhí)行。這樣可以更好地利用CPU資源,避免某個線程長時間獨占CPU。

需要注意的是,yield()方法只是一種暗示,不能保證被立即執(zhí)行或者產(chǎn)生特定的效果。具體的調(diào)度行為取決于操作系統(tǒng)和JVM的實現(xiàn)。

3.6 其他線程操作

除了以上方法,線程中還支持幾個其他的操作:

  • suspend()方法:暫時掛起線程;
  • resume()方法:恢復(fù)掛起的線程;
  • stop()方法:停止線程。

但是對于線程中 suspend()、resume()、stop() 3個方法并不推薦使用,它們也已經(jīng)被慢慢廢除掉了,主要原因是這3個方法在操作時會產(chǎn)生死鎖的問題。

打開 Thread類的源代碼,從中可以發(fā)現(xiàn) suspend()、resume()、stop() 方法的聲明上都加入了一條 "@Deprecated"的注釋,這屬于Annotation 的語法,表示此操作不建議使用。所以一旦使用了這些方法將出現(xiàn)警告信息。

既然以上3個方法不推薦使用,那么該如何停止一個線程的執(zhí)行呢?在多線程的開發(fā)中可以通過設(shè)置標志位的方式停止一個線程的運行。

//	范例 17: 停止線程運行
package com.xiaoshan.demo;

class MyThread implements Runnable { 
	private boolean flag = true;	//定義標志位屬性
	
	public void run(){	//覆寫run()方法
		int i=0;
		while(this.flag){	//循環(huán)輸出
			while(true){
				System.out.println(Thread.currentThread().getName() + "運行,i=" + (i++));     //輸出當前線程名稱
			}
		}
	}
	
	public void stop(){		//編寫停止方法
		this.flag = false;	//修改標志位
	}
}

public class StopDemo {
	public static void main(String[] args){ 
		MyThread my = new MyThread();      	//實例化 Runnable 接口對象
		Thread t = new Thread(my, "線程");	//建立線程對象
		t.start();	//啟動線程
		my.stop();	//線程停止,修改標志位
	}
}

此程序一旦調(diào)用 stop()方法就會將 MyThread 類中的 flag 變量設(shè)置為 false, 這樣 run()方法就會停止運行,這種停止方式是開發(fā)中比較推薦的。

?? 總結(jié)

本文主要介紹了多線程編程中的關(guān)鍵概念以及常用的操作方法。首先,我們了解了線程與進程之間的關(guān)系,明白了多進程、多線程、并發(fā)和并行之間的區(qū)別。接著,我們探討了多線程的實現(xiàn)方式,包括繼承Thread類、實現(xiàn) Runnable接口和利用 Callable接口實現(xiàn)多線程,并對它們進行了比較和分析。然后,我們詳細講解了線程的操作狀態(tài),幫助讀者理解線程在不同狀態(tài)間的轉(zhuǎn)換情況。最后,我們介紹了多線程常用的操作方法,如線程的命名與獲取、線程的休眠、線程優(yōu)先級、線程等待和線程讓出執(zhí)行權(quán)等。

通過本文的學習,讀者可以對多線程編程有一個更全面的認識。了解線程與進程的關(guān)系,能夠選擇適合的多線程實現(xiàn)方式。理解線程的操作狀態(tài),使得對線程的運行狀態(tài)具有更好的掌握。熟悉多線程的常用操作方法,可以對線程進行更精確的控制,提高程序的性能和并發(fā)處理能力。

總而言之,多線程編程是一項重要且常用的技術(shù)。了解多線程的相關(guān)概念和操作方法,能夠使程序員在開發(fā)過程中更好地利用多核處理器和并發(fā)處理來提高系統(tǒng)的性能和響應(yīng)能力。同時,也需要注意合理使用多線程,避免一些常見的線程安全問題和性能瓶頸。


? 溫習回顧上一篇(點擊跳轉(zhuǎn))
《【Java基礎(chǔ)教程】(四十一)常用類庫篇 · 第十一講:國際化支持類——解析 Locale 類與 ResourceBundle 類對國際化編程的支持~》

? 繼續(xù)閱讀下一篇(點擊跳轉(zhuǎn))
《【Java基礎(chǔ)教程】(四十三)多線程篇 · 下:深入剖析Java多線程編程:同步、死鎖及經(jīng)典案例——生產(chǎn)者與消費者,探究sleep()與wait()的差異》
文章來源地址http://www.zghlxwxcb.cn/news/detail-604932.html

【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~,# Java基礎(chǔ)教程,java,開發(fā)語言,學習,java-ee,jvm,后端

到了這里,關(guān)于【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java并發(fā)(1)--線程,進程,以及緩存

    Java并發(fā)(1)--線程,進程,以及緩存

    進程 進程是程序的一次執(zhí)行過程,系統(tǒng)程序的基本單位。有自己的main方法,并且主要由主方法運行起來的基本上就是進程。 線程 線程與進程相似,但線程是一個比進程更小的執(zhí)行單位。一個進程在其執(zhí)行的過程中可以產(chǎn)生多個線程。與進程不同的是同類的多個線程共享 堆

    2024年04月16日
    瀏覽(17)
  • pytorch 中的數(shù)據(jù)集與多進程并發(fā)

    需要 Dataset + collate_fn + Sampler + DataLoader 聯(lián)用, 才等價于 tf 的 dataset. DataLoader, 對外服務(wù)的類. 通過 _get_iterator () 方法返回 iterator, 對其調(diào)用 next() 得到 tensor. Sampler, 數(shù)據(jù)集的采樣策略, 給出每個 step 要使用的數(shù)據(jù)的索引, 記為 possibly_batched_index. Fetcher, 根據(jù) possibly_batched_index, 從 d

    2024年02月11日
    瀏覽(11)
  • 分布式集群與多線程高并發(fā)

    ? 后臺數(shù)據(jù)的處理語言有很多,Java 是對前端采集的數(shù)據(jù)的一種比較常見的開發(fā)語言?;ヂ?lián)網(wǎng)移動客戶端的用戶量特別大,大量的數(shù)據(jù)處理需求應(yīng)運而生??梢苿忧度胧皆O(shè)備的表現(xiàn)形式?? 很多,如 PC 端,手機移動端,智能手表,Google? 眼鏡等。Server2client 的互聯(lián)網(wǎng)開發(fā)模式比

    2024年02月08日
    瀏覽(23)
  • C++11并發(fā)與多線程筆記 (1)

    C++11并發(fā)與多線程筆記 (1)

    指在一個時間段內(nèi)有多個進程在執(zhí)行 兩個或者更多的任務(wù)(獨立的活動)同時發(fā)生(進行):一個程序同時執(zhí)行多個獨立的任務(wù); 以往計算機,單核cpu(中央處理器):某一個時刻只能執(zhí)行一個任務(wù),由操作系統(tǒng)調(diào)度,每秒鐘進行多次所謂的“任務(wù)切換”。并發(fā)的假象( 不

    2024年02月12日
    瀏覽(28)
  • Java并發(fā)(三)----創(chuàng)建線程的三種方式及查看進程線程

    Java并發(fā)(三)----創(chuàng)建線程的三種方式及查看進程線程

    例如: 輸出 注意:這里通過 @Slf4j 注解打印的日志 把【線程】和【任務(wù)】(要執(zhí)行的代碼)分開 Thread 代表線程 Runnable 可運行的任務(wù)(線程要執(zhí)行的代碼) 例如: 輸出 Java 8 以后可以使用 lambda 精簡代碼 小結(jié) 方法1 是把線程和任務(wù)合并在了一起,方法2 是把線程和任務(wù)分開

    2023年04月24日
    瀏覽(24)
  • python多進程與多線程

    python多進程與多線程

    1.1 GIL 全局解釋器鎖 其他語言,CPU是多核時是支持多個線程同時執(zhí)行。但在Python中,無論是單核還是多核,同時只能由一個線程在執(zhí)行。其根源是GIL的存在。GIL的全稱是Global Interpreter Lock(全局解釋器鎖),來源是Python設(shè)計之初的考慮,為了數(shù)據(jù)安全所做的決定。某個線程想要執(zhí)

    2024年02月05日
    瀏覽(19)
  • 一文掌握Python多線程與多進程

    并發(fā)是今天計算機編程中的一項重要能力,尤其是在面對需要大量計算或I/O操作的任務(wù)時。Python 提供了多種并發(fā)的處理方式,本篇文章將深入探討其中的兩種:多線程與多進程,解析其使用場景、優(yōu)點、缺點,并結(jié)合代碼例子深入解讀。 Python中的線程是利用 threading 模塊實現(xiàn)

    2024年02月09日
    瀏覽(17)
  • C++11并發(fā)與多線程筆記(3)線程傳參詳解,detach()大坑,成員函數(shù)做線程函數(shù)

    C++11并發(fā)與多線程筆記(3)線程傳參詳解,detach()大坑,成員函數(shù)做線程函數(shù)

    在使用detach時,不推薦引用傳遞,指針傳遞肯定有問題 在創(chuàng)建線程的同時構(gòu)造臨時對象的方法傳遞參數(shù)是可行的 如果傳遞int這種基本數(shù)據(jù)類型,推薦使用 值傳遞 ,不要用引用 如果傳遞 類對象 ,避免使用隱式類型轉(zhuǎn)換,全部都是創(chuàng)建線程這一行就創(chuàng)建出 臨時對象 ,然后在

    2024年02月12日
    瀏覽(20)
  • 【神行百里】python開啟多線程(threading)與多進程(multiprocessing)運行

    ??由于處理數(shù)據(jù)過多,程序運行很慢,就學習了一下python開啟多線程與多進程的方法,雖然最后也沒用上,但還是記錄總結(jié)一下,以備不時之需。 ??傳送門:進程與線程認識,進程與線程通俗理解 ??簡言之, 進程為資源分配的最小單元,線程為程序執(zhí)行的最小單元

    2024年02月02日
    瀏覽(31)
  • C++11并發(fā)與多線程筆記(6) unique_lock(類模板)

    unique_lock 是一個類模板。 unique_lock 比 lock_guard 靈活很多 ( 多出來很多用法 ),效率差一點,內(nèi)存占用多一些。 使用: unique_lockmutex myUniLock(myMutex); std::adopt_lock:標記作用,表示這個互斥量已經(jīng)被lock()(方便記憶:已經(jīng)被lock()收養(yǎng)了,不需要再次lock() ),即 不需要在構(gòu)造函

    2024年02月12日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包