線程的基本解析

線程對象是能夠產生線程的對象。好比在Java平臺中Thread對象,Runnable對象。線程,是指正在執行的一個指點令序列。在java平臺上是指從一個線程對象的start()開始,運行run方法體中的那一段相對獨立的過程。相比於多進程,多線程的優點有:java

    (1)進程之間不能共享數據,線程能夠;程序員

    (2)系統建立進程須要爲該進程從新分配系統資源,故建立線程代價比較小;面試

    (3)Java語言內置了多線程功能支持,簡化了java多線程編程。編程

1、建立線程和啓動多線程

  (1)繼承Thread類建立線程類ide

經過繼承Thread類建立線程類的具體步驟和具體代碼以下:性能

   • 定義一個繼承Thread類的子類,並重寫該類的run()方法;spa

   • 建立Thread子類的實例,即建立了線程對象;.net

   • 調用該線程對象的start()方法啓動線程。線程

class SomeThead extends Thraad { public void run() { //所要重寫的方法
 } } public static void main(String[] args){ SomeThread oneThread = new SomeThread(); 步驟3:啓動線程: oneThread.start(); }

 

(2)實現Runnable接口建立線程類

經過實現Runnable接口建立線程類的具體步驟和具體代碼以下:

   • 定義Runnable接口的實現類,並重寫該接口的run()方法;

   • 建立Runnable實現類的實例,並以此實例做爲Thread的target對象,即該Thread對象纔是真正的線程對象。

class SomeRunnable implements Runnable { public void run() { //所要重寫的方法 
 } } Runnable oneRunnable = new SomeRunnable(); Thread oneThread = new Thread(oneRunnable); oneThread.start();

以上的兩種方法都可實現建立線程類

然而,本魔王一開始乍一看的時候感受大致上好像並無什麼區別,但事實顯然並無這麼簡單,試問一下,當使用Thread時候若有需求要求繼承其餘類的時候,是能夠用extend繼承父類的域,那萬一要繼承的不僅是一個父類呢,Thread畢竟只是一個類,不是接口,誒!!對了,這時候用Runnable就會方便不少,下面爲你們總結的是Runnable與Thread的相關性。

 

****Runnable和Thread的區別和聯繫?****

1) Thread是一個類,Runnable是一個接口;

2) Thread類實現了Runnable接口,重寫了run方法.

3) Runnable是一個接口,定義一個類實現接口的同時還能夠繼承其餘的類 ; Runnable 支持多繼承的寫法;

4) Runable能夠簡單的實現數據的共享 ;Thread不太好實現;其實均可以實現

5) Runnable適合多個相同的程序代碼的線程去處理同一個資源,避免Java中的單繼承的限制,增長程序的健壯性,代碼能夠被多個線程共享,代碼和數據獨立。線程池只能放入實現Runnable 類線程,不能直接放入繼承Thread的類.

 

在面試的時候,不少面試官都喜歡問一些關於線程狀態的問題,可能很少問的特別細,但起碼道理咱們得說的出來,下圖是線程的生命週期,就挑幾個常見的給你們解釋的,其實有一些是我本身概括的,也有一些是網上dd下來的,懂的是什麼道理,本身整理一套白話最好。

  • 新線程:
    •  用new關鍵字和Thread類或其子類創建一個線程對象後,該線程對象就處於新生狀態。處於新生狀態的線程有本身的內存空間,經過調用start方法進入就緒狀態(runnable),它僅僅做爲一個對象實例存在, JVM沒有爲其分配CPU時間片和其餘線程運行資源;。

      注意:不能對已經啓動的線程再次調用start()方法,不然會出現Java.lang.IllegalThreadStateException異常。

       

  • 就緒狀態:
    • 在處於建立狀態的線程中調用start方法將線程的狀態轉換爲就緒狀態(儘管是採用隊列形式,事實上,把它稱爲可運行池而不是可運行隊列。由於cpu的調度不必定是按照先進先出的順序來調度的)。等待系統爲其分配CPU。等待狀態並非執行狀態,當系統選定一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態,系統挑選的動做稱之爲「cpu調度」。一旦得到CPU,線程就進入運行狀態並自動調用本身的run方法
    • 提示:若是但願子線程調用start()方法後當即執行,可使用Thread.sleep()方式使主線程睡眠一夥兒,轉去執行子線程。(sleep()方法在下面會解釋)

       

  • 運行狀態:
    • 處於運行狀態的線程是最複雜的,有阻塞狀態,就緒狀態和死亡狀態
    • 處於就緒狀態的線程,若是得到了cpu的調度,就會從就緒狀態變爲運行狀態,執行run()方法中的任務。若是該線程失去了cpu資源,就會又從運行狀態變爲就緒狀態。從新等待系統分配資源。也能夠對在運行狀態的線程調用yield()方法,它就會讓出cpu資源,再次變爲就緒狀態。(**當某個線程調用了yield()方法暫停以後,優先級與當前線程相同,或者優先級比當前線程更高的就緒狀態的線程更有可能得到執行的機會,固然,只是有可能,由於咱們不可能精確的干涉cpu調度線程。)
  • 等待/阻塞:
    • 阻塞狀態在這裏我不便多說,由於我本身都還沒看透(噴血),我只能理解的是當一個線程佔用CPU運行時被其餘線程或者語句剝奪或者說暫停了其了使用權,從而進入阻塞狀態。
    • 在阻塞狀態的線程不能進入就緒隊列。只有當引發阻塞的緣由消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,從新到就緒隊列中排隊等待,被系統選中後從原來中止的位置開始繼續運行。

 

 

 

Java提供了一些便捷的方法用於線程狀態的控制,就舉幾個經常使用的例子,多了我也不會。具體以下:

一、線程睡眠——sleep

      若是咱們須要讓當前正在執行的線程暫停一段時間,並進入阻塞狀態,則能夠經過調用Thread的sleep方法。

注:

   (1)sleep是靜態方法,最好不要用Thread的實例對象調用它,由於它睡眠的始終是當前正在運行的線程,而不是調用它的線程對象,它只對正在運行狀態的線程對象有效。以下面的例子:

 1 package day7_3HomeWork;
 2 
 3 public class Thread_text {
 4 
 5     public static void main(String[] args) {
 6         Thread_input ti = new Thread_input();
 7         ti.start();
 8 
 9     }
10 }
11 class Thread_input extends Thread{
12     String[] str = {"我","我愛","我愛福","我愛福建","我愛福建工","我愛福建工程","我愛福建工程學","我愛福建工程學院"};
13     @Override
14     public void run() {
15         // TODO Auto-generated method stub
16         for(int i=0;i<str.length;i++)
17         {
18             System.out.println(str[i]);
19             try {
20                 sleep(2000);
21             } catch (InterruptedException e) {
22                 // TODO Auto-generated catch block
23                 e.printStackTrace();
24             }
25         }    
26     }
27 }

至關於只是暫停當前的進程運行,線程處於阻塞狀態,在2000mills的睡眠時間結束的時候才能從新變回就緒狀態,而就緒狀態進入到運行狀態,是由系統控制的,咱們不可能精準的去幹涉它,因此若是調用Thread.sleep(1000)使得線程睡眠1秒,可能結果會大於1秒。下圖是sleep的方法,須要傳入的是一個long mills的參數,這是毫秒的單位。

(2)Java線程調度是Java多線程的核心,只有良好的調度,才能充分發揮系統的性能,提升程序的執行效率。可是無論程序員怎麼編寫調度,只能最大限度的影響線程執行的次序,而不能作到精準控制。

相關文章
相關標籤/搜索