【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】...
一、創(chuàng)建線程的三種方式
· 繼承Thread類
· 實現Runnable接口
· 實現Callable接口
?
二、 線程狀態(tài)
· 線程名字 getName()
· 線程活動情況 isAlive()
· 控制線程運行次序 join()
?
一、 創(chuàng)建線程的三種方式
① 繼承Thread類
/*** 步驟:* 繼承Thread重寫run方法,創(chuàng)建該線程實例,調用start()方法啟動線程* @author ChristineBassoon**/ public class test {public static void main(String[] args) {MyThread t = new MyThread();t.start();}}class MyThread extends Thread{@Overridepublic void run() {for(int i=0;i<50;i++) {System.out.println(i+"["+this.getName()+"]");}} }?
?同種方法以匿名內部類形式
new Thread(){@Overridepublic void run() {for(int i=0;i<50;i++) {System.out.println(i+"["+Thread.currentThread().getName()+"]");}} }.start();?
?
② 實現Runnable接口
/*** 步驟:* 實現Runnable接口,重寫run方法,以此Runnable實例作為Thread的target創(chuàng)建Thread對象* 調用start方法啟動線程* @author ChristineBassoon**/ public class test {public static void main(String[] args) {Thread t = new Thread(new MyRunnable());t.start();} }class MyRunnable implements Runnable{@Overridepublic void run() {for(int i=0;i<50;i++) {System.out.println(i+"["+Thread.currentThread().getName()+"]");}} }//匿名內部類形式 new Thread(new Runnable(){@Overridepublic void run() {for(int i=0;i<50;i++) {System.out.println(i+"["+Thread.currentThread().getName()+"]");}}}).start(); }?
?
③ Callable方式
/*** 步驟:* 1. 實現Callable接口,使用FutureTask類來包裝Callable對象* 2. FutureTaskd對象作為Thread對象的target創(chuàng)建并啟動線程* (FutureTask同時實現了Runnable和Callable接口,所以能作為Thread對象的的target)* 3. FutureTask的get()方法在子線程結束后可獲得返回值(以此判斷線程能否正常運行)*/ public class test {public static void main(String[] args) {CallableThread ct = new CallableThread(); FutureTask ft = new FutureTask<>(ct);new Thread(ft).start();try {System.out.println("子線程返回值為:"+ft.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}}class CallableThread implements Callable {@Overridepublic Integer call() throws Exception {for(int i=0;i<50;i++) {System.out.println(i+"["+Thread.currentThread().getName()+"]");}return 1;} }?
?
二、線程狀態(tài)
線程的幾個狀態(tài)可用圖概括 (圖源自google image),解釋得非常清楚
?
//獲取當前線程的名字 Thread.currentThread().getName(); //判斷當前線程運行情況 Thread.currentThread().isAlive(); //設定線程的名字 Thread.currentThread().setName(""); //只有該線程結束后,程序才會向下進行 [new Thread()].join();//[]表示某線程?
?
① 獲取當前線程名字 —— getName()
情況1,獲取主線程名字
public class ThreadTest {public static void main(String[] args) {System.out.println(Thread.currentThread().getName());} }?結果為
main View Code?
情況2:獲取子線程名字
new Thread() {@Overridepublic void run(){for(int i=0;i<5;i++) {System.out.println(i+"["+Thread.currentThread().getName()+"]");System.out.println(i+"["+this.getName()+"]");}} }.start();?結果為
0[Thread-0] 0[Thread-0] 1[Thread-0] 1[Thread-0] 2[Thread-0] 2[Thread-0] 3[Thread-0] 3[Thread-0] 4[Thread-0] 4[Thread-0] View Code可看出,子程序運行期間,當前的線程( Thread.currentThread() )名字就是子程序的線程名。
?
?
②線程運行情況,判斷線程是否在運行當中—— isAlive()
public class ThreadTest {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();System.out.println("");try {myThread.join();//確保子線程結束后才執(zhí)行下方語句} catch (InterruptedException e) {e.printStackTrace();}System.out.println("");System.out.println("myThread線程運行情況:"+myThread.isAlive());} }class MyThread extends Thread {public MyThread(){System.out.println("====構造函數開始====");System.out.println(this.isAlive());System.out.println("====構造函數結束====");}@Overridepublic void run(){System.out.println("=====run開始======");System.out.println(this.isAlive());System.out.println("=====run結束======");} }?結果為:
====構造函數開始==== false ====構造函數結束=========run開始====== true =====run結束======myThread線程運行情況:false View Code?總結:子線程只有調用start()方法后才會運行。
?
?
③ 線程之間的運行順序 —— join() 方法的調控
?接下來我們實驗一下:
public class condition {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.setName("子線程");//設定子線程名字myThread.start();System.out.println();System.out.println("主線程運行完畢");} }class MyThread extends Thread {@Overridepublic void run(){for(int i=0;i<20;i++) {System.out.println(i+"["+this.getName()+"]");}} }結果:
主線程運行完畢 0[子線程] 1[子線程] 2[子線程] 3[子線程] 4[子線程] 5[子線程] 6[子線程] 7[子線程] 8[子線程] 9[子線程] 10[子線程] 11[子線程] 12[子線程] 13[子線程] 14[子線程] 15[子線程] 16[子線程] 17[子線程] 18[子線程] 19[子線程] View Code如果按照執(zhí)行次序,本來應該最后打印的內容應該最后顯示的,現在卻放在最前頭了。事實上,線程之間會互相爭奪cpu資源,誰先搶到誰執(zhí)行,像上述這種情況,則是主線程先搶到了cpu資源。如果必須保證先執(zhí)行子線程,最后再執(zhí)行主線程的打印動作的話,可以使用 join() 方法控制線程之間的執(zhí)行次序。
?
我們再來實驗一下主線程和單個子線程
public class condition {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.setName("子線程");//設定子線程名字myThread.start();try {myThread.join(); } catch (InterruptedException e) {e.printStackTrace();} System.out.println("主線程運行完畢");} }class MyThread extends Thread {@Overridepublic void run(){for(int i=0;i<5;i++) {System.out.println(i+"["+this.getName()+"]");}} }?結果為
0[子線程] 1[子線程] 2[子線程] 3[子線程] 4[子線程] 主線程運行完畢?
兩個或多個子線程之間的順序同樣如此,
如果執(zhí)行順序限制為 【子線程1 → 子線程2 → 主線程結束】
public class condition {public static void main(String[] args) {MyThread t1 = new MyThread("子線程1");MyThread t2 = new MyThread("子線程2");try {t1.start();t1.join();//join()方法只有在調用start()方法后使用才有意義t2.start();t2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("主線程結束");} }class MyThread extends Thread {public MyThread(String string) {this.setName(string);}@Overridepublic void run(){for(int i=0;i<5;i++) {System.out.println(i+"["+this.getName()+"]");}} }?結果為:
0[子線程1] 1[子線程1] 2[子線程1] 3[子線程1] 4[子線程1] 0[子線程2] 1[子線程2] 2[子線程2] 3[子線程2] 4[子線程2] 主線程結束 View Code?
?
參考:https://www.cnblogs.com/songshu120/p/7966314.html(多線程創(chuàng)建的三種方式)
轉載于:https://www.cnblogs.com/tubybassoon/p/9692964.html
總結
以上是生活随笔為你收集整理的【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在公网上的Linux,我的一些配置分享
- 下一篇: 个人项目对方代码分析(随机生成不同难度试