Java多執行緒的使用有三種方法:繼承Thread類別、實作Runnable介面和使用Callable和Future建立執行緒。
一、繼承Thread類別
實作方式很簡單,只需要建立一個類別去繼承Thread類別然後重寫run方法,在main方法中呼叫該類別實例物件的start方法即可實作多執行緒並發。程式碼:
public class MyThread extends Thread { @Override public void run(){ super.run(); System.out.println("执行子线程..."); } }
測試案例:
public class Test { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); System.out.println("主线程..."); } }
運行結果:
當然,這裡的結果不代表執行緒的執行順序,執行緒是並發執行的,如果多運行幾次,列印順序可能會不一樣。在多執行緒的運行過程中,CPU是以不確定的方式去執行執行緒的,故運行結果與程式碼的執行順序或呼叫順序無關,運行結果也可能不一樣。
免費影片教學推薦:java學習影片
這裡還有一個需要注意的點就是main方法中應該呼叫的是myThread的start方法,而不是run ()方法。呼叫start()方法是告訴CPU此執行緒已經準備就緒可以執行,然後係統有時間就會來執行其run()方法。
而直接呼叫run()方法,則不是非同步執行,而是等同於呼叫函數般依序同步執行,這就失去了多執行緒的意義了。
二、實作Runnable介面
這種方式的實作也很簡單,就是把繼承Thread類別改為實作Runnable介面。程式碼如下:
public class MyRunnable implements Runnable { @Override public void run() { System.out.println("执行子线程..."); } }
測試案例:
public class Test { public static void main(String[] args) { Runnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start(); System.out.println("主线程运行结束!"); } }
運行結果:
運行結果沒啥好說的,這裡main可以看到真正創建新線程還是透過Thread創建:
Thread thread = new Thread(runnable);
這一步Thread類別的作用就是把run()方法包裝成線程執行體,然後依然透過start告訴系統這個線程已經準備好了可以安排執行。
三、使用Callable和Future建立執行緒
#上面的兩種方式都有這兩個問題:
# 1.無法取得子執行緒的回傳值;
2、run方法不可以拋出例外。
為了解決這兩個問題,我們就需要用到Callable這個介面了。說到接口,上面的Runnable接口實作類別實例是作為Thread類別的建構子的參數傳入的,之後透過Thread的start執行run方法中的內容。但是Callable並不是Runnable的子接口,是個全新的接口,它的實例不能直接傳入給Thread構造,所以需要另一個接口來轉換一下。
Java5提供了Future介面來代表Callable介面裡call()方法的回傳值,並為Future介面提供了實作類別FutureTask,該實作類別的繼承關係如圖所示:
可以看到,這個實作類別不僅實作了Future接口,還實作了Runnable接口,所以可以直接傳給Thread建構子。
而關於FutureTask的建構子如下:
所以這裡面其實就是要比上一個方法再多一個轉換過程,最終一樣是透過Thread的start來建立新執行緒。有了這個思路,程式碼就很容易理解了:
import java.util.concurrent.Callable; public class MyCallable implements Callable { int i = 0; @Override public Object call() throws Exception { System.out.println(Thread.currentThread().getName()+" i的值:"+ i); return i++; //call方法可以有返回值 } }
測試:
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class Test { public static void main(String[] args) { Callable callable = new MyCallable(); for (int i = 0; i < 10; i++) { FutureTask task = new FutureTask(callable); new Thread(task,"子线程"+ i).start(); try { //获取子线程的返回值 System.out.println("子线程返回值:"+task.get() + "\n"); } catch (Exception e) { e.printStackTrace(); } } } }
執行結果(部分):
以上是java中實作多線程的幾種方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于结构化数据处理开源库SPL的相关问题,下面就一起来看一下java下理想的结构化数据处理类库,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于PriorityQueue优先级队列的相关知识,Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于java锁的相关问题,包括了独占锁、悲观锁、乐观锁、共享锁等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于多线程的相关问题,包括了线程安装、线程加锁与线程不安全的原因、线程安全的标准类等等内容,希望对大家有帮助。

本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于关键字中this和super的相关问题,以及他们的一些区别,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于枚举的相关问题,包括了枚举的基本操作、集合类对枚举的支持等等内容,下面一起来看一下,希望对大家有帮助。

封装是一种信息隐藏技术,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法;封装可以被认为是一个保护屏障,防止指定类的代码和数据被外部类定义的代码随机访问。封装可以通过关键字private,protected和public实现。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于设计模式的相关问题,主要将装饰器模式的相关内容,指在不改变现有对象结构的情况下,动态地给该对象增加一些职责的模式,希望对大家有帮助。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。