Java中如何使用Thread和Runnable创建的线程
前言
我們都知道通過繼承Thread和實現Runnable接口都能創建線程,那么他們有什么區別呢?
繼承Thread創建線程
通過extends關鍵字繼承Thread然后覆蓋其run方法就可以實現一個自己的線程。啟動的時候只需要調用thread的start方法就可以了。
public class ExtendThreadDemo extends Thread {//定一個線程的名稱private String name;//帶參數的構造方法ExtendThreadDemo(String name) {this.name = name;}@Overridepublic void run() {System.out.println("[ExtendThreadDemo]我是線程:ExtendThreadDemo-" + name);}public static void main(String[] args) {for (int i = 0; i < 5; i++) {ExtendThreadDemo threadDemo = new ExtendThreadDemo(String.valueOf(i));threadDemo.start();}} }打印日志:
[ExtendThreadDemo]我是線程:ExtendThreadDemo-0 [ExtendThreadDemo]我是線程:ExtendThreadDemo-1 [ExtendThreadDemo]我是線程:ExtendThreadDemo-2 [ExtendThreadDemo]我是線程:ExtendThreadDemo-4 [ExtendThreadDemo]我是線程:ExtendThreadDemo-3從日志中我們可以看出,一共創建了5個線程這5個線程是異步執行的。
實現Runnable接口創建線程
通過implements關鍵字實現Runnable接口并且實現里面的run方法來創建線程。注意這里啟動線程的時候需要使用new Thread(Runable).start()方法。
public class RunnableThreadDemo implements Runnable {//定一個線程的名稱private String name;//帶參數的構造方法RunnableThreadDemo(String name) {this.name = name;}@Overridepublic void run() {System.out.println("[RunnableThreadDemo]我是線程:RunnableThreadDemo" + name);}public static void main(String[] args) {for (int i = 0; i < 5; i++) {RunnableThreadDemo threadDemo = new RunnableThreadDemo(String.valueOf(i));new Thread(threadDemo).start();}} }打印日志:
[RunnableThreadDemo]我是線程:RunnableThreadDemo3 [RunnableThreadDemo]我是線程:RunnableThreadDemo4 [RunnableThreadDemo]我是線程:RunnableThreadDemo2 [RunnableThreadDemo]我是線程:RunnableThreadDemo1 [RunnableThreadDemo]我是線程:RunnableThreadDemo0我們可以看出通過實現Runable接口的方式同樣可以達到異步執行線程的目的。
線程run方法和start方法區別
線程啟動使用的是start()方法,其實start方法里也是調用了run()方法,他們之間的區別是什么?
我們做一個測試,將上面的ExtendThreadDemo類里面的main方法稍作修改為:
也就是將里面的start()方法換成了run()方法。打印結果:
[ExtendThreadDemo]我是線程:ExtendThreadDemo-0 [ExtendThreadDemo]我是線程:ExtendThreadDemo-1 [ExtendThreadDemo]我是線程:ExtendThreadDemo-2 [ExtendThreadDemo]我是線程:ExtendThreadDemo-3 [ExtendThreadDemo]我是線程:ExtendThreadDemo-4這里線程打印結果的順序是我們同步啟動線程的順序(無論試多少次都是這個結果),這說明線程沒有異步啟動,而是同步執行了里面的run()方法而已。
start方法源碼分析
public synchronized void start() {//(1)判斷狀態是否是0。0代表是新建狀態NEW,否則拋出異常if (threadStatus != 0)throw new IllegalThreadStateException();//(2)將線程添加到線程組列表中group.add(this);//(3)將是否進入就緒態設置為falseboolean started = false;try {//(4)調用private native void start0();方法,推測方法就是請求CPU分配時間片方法start0();//(5)調用native方法成功,將狀態修改為truestarted = true;} finally {try {//(6)調用native方法失敗,將回退操作if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}第(4)這里調用了Java的native方法為:
private native void start0();所謂的navtiv方法簡單地講,一個Native Method就是一個java調用非java代碼的接口。一個Native Method是這樣一個java的方法:該方法的實現由非java語言實現,比如C。
引用:Java的native方法
https://blog.csdn.net/wike163/article/details/6635321
Thread和Runable創建線程的區別
簡單寫一個測試類CreateThreadTest里面的線程都使用內部類實現:
public class CreateThreadTest {//內部類繼承Thread創建線程private class ExtendThreadDemo extends Thread {//定一個循環數字private int a = 3;@Overridepublic void run() {//線程名稱String name = Thread.currentThread().getName();System.out.println(name + " 創建成功");while (a > 0) {a--;System.out.println("[ExtendThreadDemo]" + name + "我是數字:" + a);}}}//內部類繼承實現Runnable創建線程private class RunnableThreadDemo implements Runnable {//定一個循環數字private int a = 3;@Overridepublic void run() {//線程名稱String name = Thread.currentThread().getName();System.out.println(name + " 創建成功");while (a > 0) {a--;System.out.println("[ExtendThreadDemo]" + name + "我是數字:" + a);}}}//使用extend創建線程測試public void extendThreadTest() {ExtendThreadDemo extendThreadDemo1 = new ExtendThreadDemo();ExtendThreadDemo extendThreadDemo2 = new ExtendThreadDemo();ExtendThreadDemo extendThreadDemo3 = new ExtendThreadDemo();extendThreadDemo1.start();extendThreadDemo2.start();extendThreadDemo3.start();}//使用implements創建線程測試public void runnableThreadTest() {RunnableThreadDemo runnableThreadDemo = new RunnableThreadDemo();Thread runnableThreadDemo1 = new Thread(runnableThreadDemo);Thread runnableThreadDemo2 = new Thread(runnableThreadDemo);Thread runnableThreadDemo3 = new Thread(runnableThreadDemo);runnableThreadDemo1.start();runnableThreadDemo2.start();runnableThreadDemo3.start();}//main方法測試public static void main(String[] args) {CreateThreadTest mainTest = new CreateThreadTest();mainTest.extendThreadTest(); // mainTest.runnableThreadTest();} }當使用extendThreadTest進行測試的時候,打印日志如下:
Thread-0 創建成功 [ExtendThreadDemo]Thread-0我是數字:2 [ExtendThreadDemo]Thread-0我是數字:1 [ExtendThreadDemo]Thread-0我是數字:0 Thread-1 創建成功 [ExtendThreadDemo]Thread-1我是數字:2 [ExtendThreadDemo]Thread-1我是數字:1 [ExtendThreadDemo]Thread-1我是數字:0 Thread-2 創建成功 [ExtendThreadDemo]Thread-2我是數字:2 [ExtendThreadDemo]Thread-2我是數字:1 [ExtendThreadDemo]Thread-2我是數字:0當使用runnableThreadTest進行測試的時候,打印日志如下:
Thread-0 創建成功 [ExtendThreadDemo]Thread-0我是數字:2 [ExtendThreadDemo]Thread-0我是數字:1 [ExtendThreadDemo]Thread-0我是數字:0 Thread-1 創建成功 Thread-2 創建成功從以上結果我們可以看出,如果繼承Thread的話里面的變量在每一個線程中都會各自復一份,但是如果使用Runable多個線程之間可以共享數據變量。
關于線程的生命周期可以參考:JAVA線程的生命周期以及5種狀態轉換
https://blog.csdn.net/u011047968/article/details/106857781
總結
以上是生活随笔為你收集整理的Java中如何使用Thread和Runnable创建的线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吐血整理:Java线程池源码分析(基于J
- 下一篇: 吐血总结:AQS到底是什么?