多線程Runnable和Callable簡介筆記

多線程實現
一、多線程的四種實現方式

1.繼承Thread類(Thread實現Runnable接口)
2.實現Runnable接口
3.線程池
4.實現Callable接口

二、Callable的實現方式

首先, Java所有關於多線程的操作,都是Runnable的實現,但是Callable接口並沒有繼承Runnable接口,所以不能直接使用Callable實現多線程

通過查看JDK1.8文檔, 可以看到Runnable有許多實現類,其中一個是FutureTask的實現類
在這裏插入圖片描述
查看源碼,可以看到FutureTask類實現了RunnableFuture接口
在這裏插入圖片描述
RunnableFuture接口繼承了Runnable和Future接口
在這裏插入圖片描述
再看一下FutureTask實現類的構造方法
有兩個構造方法,第一個, 需要傳入Runnable的實現,不是我要的
在這裏插入圖片描述
第二個,傳入Callable接口的實現,通過這個構造方法,就可以通過實現Callable接口的方式實現多線程在這裏插入圖片描述

Callable是一個函數式接口,只需要實現一個方法, call方法
在這裏插入圖片描述

三、Callable實現多線程Demo

創建一個ProjectPrice類模擬計算工程價格的業務, 實現Callable接口, 實現其中的call方法, 返回Integer類型數據

public class ProjectPrice implements Callable<Integer> {

	private Integer price;

	private String productName;

	@Override
	public Integer call() throws Exception {
		if (productName.equals("材料")) {
			TimeUnit.SECONDS.sleep(3);
			System.out.println("正在計算材料價格");
			price = 100;
		}
		if (productName.equals("人工")) {
			TimeUnit.SECONDS.sleep(2);
			System.out.println("正在計算人工價格");
			price = 20;
		}
		return price;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

}

測試類, 創建兩個線程,分別計算材料費和人工費

public class Test1 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		System.out.println("開始覈算工程價格");
		
		ProjectPrice projectPrice1 = new ProjectPrice();
		projectPrice1.setProductName("人工");
		//創建FutureTask,調用構造方法,傳入Callable實現類
		FutureTask<Integer> futureTask1 = new FutureTask<Integer>(projectPrice1);
		//創建線程,傳入FutureTask,開啓多線程
		new Thread(futureTask1).start();

		ProjectPrice projectPrice2 = new ProjectPrice();
		projectPrice2.setProductName("材料");
		FutureTask<Integer> futureTask2 = new FutureTask<Integer>(projectPrice2);
		new Thread(futureTask2).start();

		//通過FutureTask的get方法,獲取計算結果
		Integer rengong = futureTask1.get();
		Integer cailiao = futureTask2.get();

		System.out.println("人工費用: " + rengong);
		System.out.println("材料費用: " + cailiao);
		System.out.println("共花費: " + (rengong + cailiao));

	}
}

輸出結果:

開始覈算工程價格
正在計算人工價格
正在計算材料價格
人工費用: 20
材料費用: 100
共花費: 120

四、總結
1)不是說Java中多線程的實現都必須要實現Runnable接口嗎?爲什麼這裏只實現callable接口就可以了.

答: 在創建多線程的時候,傳入到Thread構造方法中的參數是FutureTask,而FutureTask實現了RunnableFuture接口,RunnableFuture接口繼承了Runnable接口,其實是間接實現了Runnable接口
在這裏插入圖片描述

2)Runnable接口必須要實現run方法,爲什麼沒有實現run方法也可以實現多線程?

答: 因爲FutureTask已經幫我們實現了run方法, 再run方法中, FutureTask會幫我們調用callable接口的call方法,所以只需要實現call方法即可
在這裏插入圖片描述

3)Runnable和Callable的區別

Runnable實現run方法,沒有返回值
Runable是java.lang包下的接口
Runnable是java原生的多線程頂端接口,可以直接實現多線程

Callable實現call方法
Callable是JUC包下的接口, 更高級的接口
Callable是另外的實現多線程的方式, 和多線程之間並沒有直接關係, 需要通過FutureTask中間類來實現多線程操作
Callable通過get方法獲取返回值的時候,會阻塞當前主線程,直到獲取到值後再繼續執行主線程

筆記有誤的話,請指出,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章