Thread 中的run() 与start() 方法
將類聲明為 Thread 的子類是創建線程的方式之一,如果我們想要在線程內定義任務那么就要重寫Thread 中的run() 方法。start() 方法使我們定義的線程執行,我們已經將線程的任務定義在了run() 方法中為什么run() 方法不是執行線程的方法而是start() 方法呢?當時學線程的時候并沒有多考慮這個問題,由于以前有一些誤解,現在就寫出來供自己與大家參考。
??????我定義了一個Thread 的子類ThreadTest ,在該子類中重寫了run() 方法,在run() 方法中用于輸出當前正在執行的線程引用,為了達到效果我讓線程等待了100ms。在創建兩個線程對象thread1 與thread2 后直接調用了它們的run() 方法,我們希望得到的結果是thread1 與thread2 共同搶占CPU 以達到交錯輸出,但是從輸出的結果看出在執行的始終是主線程(main)。
public class ThreadTest extends Thread{@Overridepublic void run() {for(int i = 0; i < 5; i++){try {Thread.sleep(100);//Thread.currentThread() 返回對當前正在執行的線程對象的引用System.out.println(Thread.currentThread());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {TestThread thread1 = new TestThread();TestThread thread2 = new TestThread();thread1.run();thread2.run();} }輸出:
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
??????下面我們用和上面同樣的代碼,不再調用ThreadTest 的run() 方法,這次調用start() 方法,看看輸出結果會是什么?從下面的結果可以看出這次輸出的不再是主線程,而是線程0與線程1 (但是執行的線程也包括主線程)。
public class ThreadTest extends Thread{@Overridepublic void run() {for(int i = 0; i < 3; i++){try {Thread.sleep(100);//Thread.currentThread() 返回對當前正在執行的線程對象的引用System.out.println(Thread.currentThread());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {TestThread thread1 = new TestThread();TestThread thread2 = new TestThread();thread1.start();thread2.start();} }輸出
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
??????通過執行run() 方法與start() 方法可以知道Thread 并不是通過run() 方法執行線程的而是通過start() 方法執行線程,我們只是把線程的任務定義在了run() 方法中,但是它并不是執行任務的方法。我們知道創建執行線程任務還有一種方式,就是實現Runnable 接口。下面我們就來看一下Runnable 中的run() 方法,為了更好的對比我在run() 方法中定義了和上面一樣的任務。通過上面的了解我們知道執行run() 方法并不能讓線程執行,所以輸出的仍然是主線程的引用。
public class RunnableTest implements Runnable {@Overridepublic void run() {for(int i = 0; i < 3; i++){try {Thread.sleep(100);System.out.println(Thread.currentThread());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {RunnableTest runnableTest1 = new RunnableTest();RunnableTest runnableTest2 = new RunnableTest();runnableTest1.run();runnableTest2.run();} }輸出
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
??????通過看Runnable 接口的源碼你就會知道這個接口只定義了一個run() 方法,這也說明著Runnable 并不能創建線程實例,那么怎么執行在其中定義的任務呢?想要創建線程實例還不簡單嗎,直接new 一個Thread 對象不就好了嗎。Thread類 提供了一個 Thread(Runnable target) 構造器,它允許我們傳入一個Runnable 子類的實例,下面我們就來這么做。
@FunctionalInterface public interface Runnable {/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see java.lang.Thread#run()*/public abstract void run(); }??????重新定義了兩個Thread 類實例并將RunnableTest 對象傳入Thread 類中的構造器,然后由線程實例thread1 與thread2 執行線程任務,我們看到正如我們所希望的那樣打印著執行線程的引用。
public class RunnableTest implements Runnable {@Overridepublic void run() {for(int i = 0; i < 3; i++){try {Thread.sleep(100);System.out.println(Thread.currentThread());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {RunnableTest runnableTest1 = new RunnableTest();RunnableTest runnableTest2 = new RunnableTest();Thread thread1 = new Thread(runnableTest1);Thread thread2 = new Thread(runnableTest2);thread1.start();thread2.start();} }輸出
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
總結:
??????Thread 中的run() 方法只是定義了線程的任務但是它不負責執行該任務,如果你調用該方法那么執行的只是主線程,就像某一個對象實例調用它自己的方法一樣。
??????Thread 中的start() 方法才是執行線程的方法,在執行該方法時,Java 虛擬機會調用該線程的run() 方法,從而達到并發執行的目的。在這里你需要注意的是多次啟動一個線程是不安全的,特別是線程執行結束后,不要再重新啟動,這點要特別注意。
??????在這里也通過實現Runnable 接口來定義線程任務,需要注意的是Runnable 接口的實現并不能創建線程實例,當你想要執行其中定義的任務時,你需要將該子類的實例作為參數傳入Thread 中的構造器,通過Thread 類的實例來執行線程任務。
總結
以上是生活随笔為你收集整理的Thread 中的run() 与start() 方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 木乃以布+彝族话怎么读?
- 下一篇: 兰陵县税郭邮政编码?