簡體   English   中英

這兩種啟動線程的方式有什么區別?

[英]What are the differences between these two ways of starting threads?

如果我有一個實現Runnable接口的類,那么main方法中這些語句之間的區別是什么?

MyThread t1 = new MyThread();
t1.start();

MyThread t2 = new MyThread();
new Thread(t2).start();

由於您做了t1.start() ,因此我假設MyThread擴展了Thread。 在這種情況下,第一個是正確的。

第二個創建新線程,然后在另一個線程中啟動任務。 浪費了一個線程。

要在Java中實現線程,您基本上有兩個選擇。 一:擴展Thread類並實現方法運行。 您的示例似乎就是這種情況。 在這種情況下,您應該調用Thread.class的start()方法。 那是您提供的兩個變量之一。

第二種變體是如果您實現Runnable-interface。 在這種情況下,您還實現了方法run,但是您的類沒有開始,因此您將Runnable作為參數創建了一個新的Thread-class(就像您在第二個示例中所做的那樣)。 但這沒有意義,如果您已經擴展了Thread。

我個人更喜歡實現Runnable,因為我不更改Thread(將對其進行擴展)的行為,而僅使用Thread-functionity。

假如說

class MyThread extends Thread

第一次調用將在新線程中啟動代碼。

通話

new Thread(new MyThread()).start();

也會在MyThread中運行您的代碼,因為Thread構造函數僅需要一個實現Runnable接口和run()方法的對象。 您的MyThread類已經具有此方法,因此它將由簡單的包裝線程執行。 還要注意,新的MyThread基本上仍然是未啟動的線程。

您可以嘗試以下小程序:

public class MyThread extends Thread {
    public void run() {
        if (Thread.currentThread() != this) {
            System.out.println("Wrapped into a separate thread");
            start();
        } else {
            System.out.println("MyThread run as expected");
        }
    }
    public static void main(String[] args) {
        new Thread(new MyThread ()).start();
    }
}        

為了使名稱更容易混淆,讓我們來看另一個示例:

public class MyJPanel extends JPanel implements Runnable {
    public void run() {
        System.out.println("Hello MyJPanel");
    }
    public static void main(String[] args) {
        new Thread(new MyJPanel()).start();
    }
}

第一個調用(如果它將是run())將在當前線程中執行,而第二個調用將創建一個新線程,該線程將運行您的Runnable的run()方法。

在第二篇中,您將創建一個不包含在變量中的新線程,並啟動該新線程。 t2保持不變。

在第一個中,您創建t1並開始...

我認為第二是沒有意義的

每當您的班級需要擴展另一個班級時,請使用Runnable。

而且Runnable界面僅包含run方法而無法啟動。

假設MyThread僅實現Runnable接口,第二個代碼段就是使用的正確模式。 Thread.start()鏈接到本機方法,該方法將產生新線程。 然后,它將調用自己的run() ,后者將在其實例Runnable變量上調用run() 在第二個代碼段中,這將是MyThread的實例,即Runnable

根據您提供的信息,第一個代碼段將不會編譯,除非:

  • 您已經自行實現了start方法。 在這種情況下,您的代碼將不會啟動新線程,並且您將僅按照MyThread.start()定義的當前線程進行操作。
  • 您實際上已經擴展了Thread並實現了Runnable 如果是這種情況,則Runnable接口是多余的,因為Thread也會實現此接口。 另外,如果要覆蓋start方法,則應格外小心,因為如果要使用新線程,則需要對super進行調用。 至少由於這個原因,最好只讓類實現Runnable而不擴展Thread 此外,如果僅實現Runnable ,則最好不要在名稱中使用Thread一詞。

MyThread t1 =新的MyThread(); t1.start();

將是編譯時異常

MyThread t2 =新的MyThread(); 新線程(t2).start();

會正常工作。可運行接口沒有啟動方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM