2017-02-20 118 views
1

根據標題,看一下這個代碼:在另一個線程中使用線程是否是一個好習慣?

Thread outer = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       Thread inner1 = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         //some statements and other inner threads 
        } 
       }); 

       Thread inner2 = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         //some statements and other inner threads 
        } 
       }); 

       //some statements and other inner threads 
      } 
     }); 

所以,這是一個好的做法是使用多線程這樣嗎?

Regards

+1

請嘗試堅持每個問題1個問題。 – Kayaman

+0

@Kayaman對不起...我只是不想發3帖子。如果它不好,我會編輯它併發送另外2個帖子。我應該這樣做嗎? – HMD

+0

那麼目前這個問題有點太大,無法正確回答。 – Kayaman

回答

1

根據Q1「很好」。這是正確的,但創建威脅只是爲了創建另一個線程沒有多大意義。

另外,請記住,創建一個Thread對象是相對昂貴的操作。 您在代碼中有//some statements and other inner threads評論。考慮使用ThreadPoolExecutor來避免手動創建多個線程。

1

Java Code Geeks關於併發性的文章對您有幾點建議。我建議你將其全部讀它,但這裏有兩個重要的片段:

通常情況下,不建議直接創建和管理使用Thread類的實例線程...

和這個:

在Java中創建新線程很簡單,但管理它們真的很難。 Java標準庫提供了極其有用的抽象概念,其執行者和線程池的形式可以簡化線程管理。

實質上,在其最簡單的實現中,線程池創建並且維護一個線程列表,準備馬上使用。 應用程序,而不是每次產生新的線程,只是從池中借用 (或根據需要)。一旦借用線程 完成其作業,它將返回到池中,並且變爲 可用於接收下一個任務。

雖然可以直接使用線程池,Java標準 庫提供一個executors外觀,其具有一組工廠方法 的創建常用線程池配置。

線程有很多國家的管理,這也是在文章中確定:

  • :尚未啓動的線程處於這種狀態。
  • RUNNABLE:在Java虛擬機中執行的線程處於此狀態。
  • BLOCKED:阻塞等待監視器鎖定的線程處於此狀態。
  • WAITING:無限期等待另一個線程執行特定操作的線程處於此狀態。
  • TIMED_WAITING:無限期等待另一個線程執行特定操作的線程處於此狀態。
  • TERMINATED:已退出的線程處於此狀態。

以下是一些其他方面的考慮,從下面的答案this question

  1. Consider non-blocking I/O

    是的,你可以根據需要推出儘可能多的線程,但是這可能 不是最好的要走的路。使用非阻塞API的 好得多,這樣你就可以開始執行一些外部調用,並且調用線程可以立即開始做其他事情,而不用等待 socket /數據庫調用返回。然後,當套接字/數據庫 調用回來時,會觸發回調來完成該處理。

    非阻塞因爲你 只是觸發呼叫和註冊回調,並沒有嘗試 平衡併發線程基本都是 只是在睡覺反正的「正確」數字I/O能夠提供遠遠優於CPU利用率。

  2. Consider thread hierarchy

是層次很重要?

您可能最好使用ExecutorService和緩存的 線程池。

這種方式可以將線程池​​而不是創建批次(這是昂貴的 )。 ExecutorServices還提供了其他很酷的功能,並且使用它們的Callables/Runnables可能比使用自己的線程更容易測試。

+0

Re,「通常,不建議使用Thread class_實例直接創建和管理線程。」這是IMO的不好建議。如果你想要一個長期運行的專用線程,那麼實例化'Thread'就是獲得它的最簡單方法。儘管更簡單==好,但是,您可能希望使用'ThreadFactory'來代替。現在,我們可以爭論你是否應該運行一個長期運行的專業化線程,但這是另一個需要討論的話題。 –

+0

我不知道是否「更簡單」在考慮線程生命週期,資源管理,持久性,監控,標準化/易讀性等方面的權衡時具有足夠的權重。[Here](http://stackoverflow.com/a/34373289/2356554)是關於單個線程與Executor庫有關的有趣答案。另外,直接從Oracle獲得[良好參數](http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html)總是更喜歡併發包。 – Keith

2

在任何編程語言中都沒有內部線程。線程只是具有run()方法的對象,具有幾個線程可以同時運行(同時)的功能。

在您的示例中,您在線程的run()方法內創建了兩個線程。這不是問題,因爲您可以在任何上下文中創建對象。

如果你想使用線程,你必須在創建線程之後調用outer.start(),inner1.start()inner2.start(),否則它們不會被執行。再說一次,這絕對沒問題,因爲Thread在哪個上下文中開始並不重要;所有線程均由Java虛擬機平等對待。

1

我不喜歡這種方式,因爲:

*的可讀性

*線程2將自動挑選線程1優先,除非你不手動

*線程調度基於JVM(如時間段設置,排隊......),所以你不知道線程1何時會通過可運行狀態

*如果線程2依賴線程1,則可以使用wait和notify或其他新功能來實現此目標,以便它更易讀

相關問題