深入探究Java線程的創(chuàng)建與構造方法
一、創(chuàng)建線程
啟動線程—start 方法
通過覆寫 run 方法創(chuàng)建?個線程對象,但線程對象被創(chuàng)建出來并不意味著線程就開始運行了
- 覆寫run方法是給線程指令清單
- 但是start方法,則是讓線程去真正的執(zhí)行
方法一
繼承Thread類
/**
* 繼承Thread創(chuàng)建線程
*/
class MyThread1 extends Thread{
@Override
public void run() {
//業(yè)務代碼
Thread thread = Thread.currentThread();
System.out.println("名稱:" + thread.getName());
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
//獲得當前的線程
Thread mainThread = Thread.currentThread();
System.out.println("名稱:" + mainThread.getName());
Thread thread = new MyThread1();
//開啟線程
thread.start();
}
}因為 Java 是單繼承,繼承了 Thread 就不能繼承其他類了,然而 Java 可以實現(xiàn)多個接口,于是有了下?種方式
方法二
實現(xiàn)Runnable接口
/**
* 使用Runnable接口創(chuàng)建線程
*/
class MyThread2 implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread();//得到當前線程
System.out.println("名稱:" + thread.getName());
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
MyThread2 myThread2 = new MyThread2();
//創(chuàng)建線程
Thread thread = new Thread(myThread2);
//啟動線程
thread.start();
}
}方法三
繼承Thread類使用匿名內(nèi)部類
/**
* 繼承Thread使用匿名內(nèi)部類創(chuàng)建
*/
public class ThreadDemo4 {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
// 業(yè)務代碼
Thread thread2 = Thread.currentThread();
System.out.println("名稱" + thread2.getName());
}
};
//開始線程
thread.start();
}
}方法四
實現(xiàn)Runnable接口,使用匿名內(nèi)部類
/**
* runnable使用匿名內(nèi)部類創(chuàng)建
*/
public class ThreadDemo3 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//具體業(yè)務
Thread thread1 = Thread.currentThread();
System.out.println("名稱:" + thread1.getName());
}
});
//開啟線程
thread.start();
}
}方法五
使用lambda表達式
/**
* 使用lambda表達式
*/
public class ThreadDemo5 {
public static void main(String[] args) {
//創(chuàng)建線程
Thread thread = new Thread(()->{
//業(yè)務代碼
Thread thread3 = Thread.currentThread();
System.out.println("名稱" + thread3.getName());
});
//啟動線程
thread.start();
}
}方法六
帶返回值的 Callable
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 使用callable創(chuàng)建線程
*/
public class ThreadDemo6 {
public static void main(String[] args)throws ExecutionException, InterruptedException {
// 創(chuàng)建 Callable 實例
MyCallable callable = new MyCallable();
// 用于接收 Callable 結(jié)果的對象
FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
// 創(chuàng)建新線程
Thread thread = new Thread(futureTask);
// 啟動線程
thread.start();
// 接收新線程執(zhí)行的結(jié)果
int result = futureTask.get();
System.out.println(Thread.currentThread().getName() +
"——新線程返回的結(jié)果為:" + result);
}
}
/**
* Callable<V> 泛型里面可以是任意數(shù)據(jù)類型
*/
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 生成隨機數(shù):0-9
int randomNum = new Random().nextInt(10);
System.out.println(Thread.currentThread().getName() +
"——隨機數(shù):" + randomNum);
return randomNum;
}
}在創(chuàng)建線程時, 如果是 JDK 1.8 以上版本,在不需要獲得線程執(zhí)行結(jié)果的情況下,推薦使用Lambda 方式來創(chuàng)建線程,因為它的寫法足夠簡潔;如果想要獲取線程執(zhí)行結(jié)果,可使用FutureTask + Callable 的方式來實現(xiàn)
二、run方法和start方法的區(qū)別
run 方法和 start 方法的主要區(qū)別如下:
①方法性質(zhì)不同
run 是一個普通方法,而 start 是開啟新線程的方法。

②執(zhí)行速度不同
調(diào)用 run 方法會立即執(zhí)行任務,調(diào)用 start 方法是將線程的狀態(tài)改為就緒狀態(tài),不會立即執(zhí)行。
③調(diào)用次數(shù)不同
run 方法可以被重復調(diào)用,而 start 方法只能被調(diào)用一次。start 方法之所以不能被重復調(diào)用的原因是,線程的狀態(tài)是不可逆的,Thread 在 start 的實現(xiàn)源碼中做了判斷,如果線程不是新建狀態(tài) NEW,則會拋出非法線程狀態(tài)異常IllegalThreadStateException
public static void main(String[] args) {
// 創(chuàng)建線程一
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當前執(zhí)行的線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程一,線程名:" + currThread.getName());
}
});
// 調(diào)用 run 方法
thread.run();
// 多次調(diào)用 run 方法
thread.run();
// 創(chuàng)建線程二
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當前執(zhí)行的線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程二,線程名:" + currThread.getName());
}
});
// 調(diào)用 start 方法
thread2.start();
// 多次調(diào)用 start 方法
thread2.start();
}
從上述結(jié)果可以看出,run 方法多次調(diào)用可用正常執(zhí)行,而第二次調(diào)用 start 方法時程序就報錯了,提示“IllegalThreadStateException”非法線程狀態(tài)異常
總結(jié)
方法性質(zhì)不同:run 是一個普通方法,而 start 是開啟新線程的方法。
執(zhí)行速度不同:調(diào)用 run 方法會立即執(zhí)行任務,調(diào)用 start 方法是將線程的狀態(tài)改為就緒狀態(tài),不會立即執(zhí)行。
調(diào)用次數(shù)不同:run 方法可以被重復調(diào)用,而 start 方法只能被調(diào)用一次。
三、線程的構造方法

1、Thread()創(chuàng)建線程
Thread t1 = new Thread();
2、Thread(Runnable target) 創(chuàng)建線程
Thread t2 = new Thread(new MyRunnable());
3、Thread(String name)創(chuàng)建線程且命名
/**
* 創(chuàng)建線程,構造方法設置線程名稱
*/
public class ThreadDemo9 {
public static void main(String[] args) {
//構造方法設置名稱
Thread thread = new Thread("線程1"){
@Override
public void run() {
//休眠線程
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
}4、Thread(Runnable target, String name),用Runnable 對象創(chuàng)建線程對象,并命名
/**
* 創(chuàng)建線程,并設置名稱
*/
public class ThreadDemo10 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"Runable-Thread");
thread.start();
}
}到此這篇關于深入探究Java線程的創(chuàng)建與構造方法的文章就介紹到這了,更多相關Java線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Boot Actuator監(jiān)控的簡單使用方法示例代碼詳解
這篇文章主要介紹了Spring Boot Actuator監(jiān)控的簡單使用,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Springboot項目出現(xiàn)java.lang.ArrayStoreException的異常分析
這篇文章介紹了Springboot項目出現(xiàn)java.lang.ArrayStoreException的異常分析,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-12-12
Eclipse創(chuàng)建java程序可執(zhí)行jar包教程
這篇文章主要為大家分享了Eclipse創(chuàng)建java程序可執(zhí)行jar包教程,具有一定的實用性和參考價值,感興趣的小伙伴們可以參考一下2016-05-05
JAVA使用commos-fileupload實現(xiàn)文件上傳與下載實例解析
這篇文章主要介紹了JAVA使用commos-fileupload實現(xiàn)文件上傳與下載的相關資料,需要的朋友可以參考下2016-02-02

