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

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

1、Thread()創(chuàng)建線(xiàn)程
Thread t1 = new Thread();
2、Thread(Runnable target) 創(chuàng)建線(xiàn)程
Thread t2 = new Thread(new MyRunnable());
3、Thread(String name)創(chuàng)建線(xiàn)程且命名
/**
* 創(chuàng)建線(xiàn)程,構(gòu)造方法設(shè)置線(xiàn)程名稱(chēng)
*/
public class ThreadDemo9 {
public static void main(String[] args) {
//構(gòu)造方法設(shè)置名稱(chēng)
Thread thread = new Thread("線(xiàn)程1"){
@Override
public void run() {
//休眠線(xiàn)程
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
}4、Thread(Runnable target, String name),用Runnable 對(duì)象創(chuàng)建線(xiàn)程對(duì)象,并命名
/**
* 創(chuàng)建線(xiàn)程,并設(shè)置名稱(chē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();
}
}到此這篇關(guān)于深入探究Java線(xiàn)程的創(chuàng)建與構(gòu)造方法的文章就介紹到這了,更多相關(guān)Java線(xiàn)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中有關(guān)構(gòu)造方法中的輸出
- Java基礎(chǔ)學(xué)習(xí)之構(gòu)造方法詳解
- java線(xiàn)程組構(gòu)造方法源碼解析
- 詳解Java的構(gòu)造方法及類(lèi)的初始化
- java中構(gòu)造方法及this關(guān)鍵字的用法實(shí)例詳解(超詳細(xì))
- Java字節(jié)緩存流的構(gòu)造方法之文件IO流
- Java構(gòu)造方法和方法重載詳解
- Java 構(gòu)造方法的使用詳解
- Java構(gòu)造方法 super 及自定義異常throw合集詳解用法
- java構(gòu)造器 默認(rèn)構(gòu)造方法及參數(shù)化構(gòu)造方法
- Java構(gòu)造方法有什么作用?
java寫(xiě)卷積神經(jīng)網(wǎng)絡(luò)(CupCnn簡(jiǎn)介)
使用Jmeter進(jìn)行http接口測(cè)試的詳細(xì)流程
Java使用Armitage進(jìn)行滲透測(cè)試的方法
java使用動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)AOP(日志記錄)的實(shí)例代碼
RestTemplate使用不當(dāng)引發(fā)的問(wèn)題及解決
spring三級(jí)緩存以及為什么不用二級(jí)緩存解讀

