Java學習筆記之線程

Java學習筆記之線程

線程的定義

線程有兩種定義方法:一是繼承Thread類;二是實現Runabble接口。

繼承Thread類定義線程

Thread類中有一個run方法,定義的線程需要重寫這個方法。在重寫run方法時,可以定義該線程所執行的語句。當線程啟動時,run方法中的語句就會成為一個獨立的線程。

public class LianXi extends Thread {
  public void run(){
  System.out.println("通過繼承Thread類定義線程!");
 }
}

繼承Thread類定義線程后創建線程對象:

LianXi x=new LianXi();

從創建的線程對象中可以看出,創建對象的方法和創建普通對象的方法是一樣的。


實現Runnable接口定義線程

Runable接口中也有一個run方法,該run方法就會作為線程的一個執行方法。

public xlass LianXi2 implements Runnable {
    public void run(){
        System.out.println("通過實現Runnable接口定義線程")            
        }
                                            }

在使用Runnable接口定義線程的方法中,要想創建線程對象需要借助Thread類。Thread類具有四個構造器 ,最常用的就是具有一個參數的構造器,這就是實現Runnable接口對象的構造器。創建線程對象的程序如下:

LianXi2 x1=new LianXi2();
Thread t=new Thread(x1);

運行線程

啟動線程

想要啟動一個線程需要調用線程對象的start方法。

    class MyRunnable implements Runnable {
//定義一個run線程方法 public void run()
{
System.out.println("這是一個正確的啟動線程的程序"); }
}
public class XianCheng4 {
public static void main(String args[]) {
MyRunnable mr=new MyRunnable(); Thread t=new Thread(mr);
t. start (); //啟動線程
} }

在上面的實例中我們可以看到,程序運行時調用的是start方法,運行的則是run方法。整個程序之所以這么設計體現了java的多線程的概念。在調用start方法后就啟動了一個線程,該線程是和main方法并列的線程,這樣一來整個程序中就有了兩個線程變成了多線程程序。

注意:線程只能被啟動一次,即只能調用一次start方法。當多次啟動線程,也就是多次調用start方法時就會發生異常。

同時運行多個線程

class MyRunnable implements Runnable {
//定義一個run線程方法 public void run()
{
System.out.println("這是一個正確的啟動線程的程序"); }
}
public class XianCheng4 {
public static void main(String args[]) {
MyRunnable mr=new MyRunnable(); Thread t=new Thread(mr);
t. start (); //啟動線程
} }

在同時運行多個線程時,運行的結果是不唯一的。因為程序在運行編譯時有很多不確定的因素,首先就是線程的執行順序是不確定的,線程間交替也是不確定的。

線程的生命周期

線程是存在生命周期的。線程的生命周期分為五種不同的狀態,分別是新建狀態準備狀態運行狀態等待/阻塞狀態死亡狀態

新建狀態

當一個線程被創建后,線程就處于新建狀態。處于該狀態的線程在調用了start方法之后,進入準備狀態。從新建狀態只能進入準備狀態,不能從其他狀態進入新建狀態。

準備狀態

從新建狀態調用start方法進入準備狀態的線程隨時都可能被選中進入運行狀態,從而執行線程。不過處于準備狀態的線程不止一個,對于那一個線程被選中進入運行狀態是不確定的。另外,在等待/阻塞狀態的線程被解除等待和阻塞后不能直接進入運行狀態,而是要進入準備狀態讓系統來進行選擇。

運行狀態

處于準備狀態的線程一旦被系統選中之后就進入了運行狀態,同時線程獲取了CPU的時間。在運行狀態的線程將執行run方法中的語句,不過運行狀態下的線程也不是很快就能執行結束的,運行狀態下的線程隨時都可能被調度程序調度回準備狀態。在運行狀態還可以讓線程進入等待/阻塞狀態。
在通常的單核CPU中,在同一個時刻,只有一個線程處于運行狀態。在多核的CPU中,就可能有兩個或多個線程處于運行狀態。這就是多核系統運行更快的原因。

等待/阻塞狀態

在java中定義了許多線程調度的方法,包括睡眠、阻塞、掛起和等待。使用這些方法都會將處于運行狀態的線程調度到等待/阻塞狀態。

死亡狀態

當線程中的run方法執行結束后,或者程序發生異常終止運行后,相應的線程進入死亡狀態。進入死亡狀態后的線程不能通過調用start方法重新啟動線程。但是死亡的線程依然可以被當作普通的類來使用。

線程調度

睡眠方法

當線程處于運行狀態時,調用sleep睡眠方法將使線程從運行狀態 進入等待/阻塞狀態,從而使程序停止運行。sleep睡眠方法是具有一個時間參數的,當經過這么長時間后,線程將進入準備狀態 ,等待系統的調度。從而可以看出,當線程調用睡眠方法后,要想回到運行狀態,需要的時間要比指定的睡眠時間長。
sleep方法被重載,存在兩種方式,sleep的基本語法格式如下:

public static void sleep(long millis) throws InterruptedException;

public static void sleep(long millis,int nanos) throws InterruptedException;

使用這兩個方法都能讓線程進入睡眠狀態,mills參數表示線程的睡眠毫秒數;nanos表示線程睡眠的納秒數。

注意:sleep方法是可能發生異常的,所以在使用sleep方法是需要進行異常捕獲。

線程的優先級

在大部分的系統中,線程是采用優先級的方法進行調度的。在Java中線程也是采用優先級的方式進行調度的,優先級高的線程就能占用更多的CPU資源和更高的被執行概率。

Java中的優先級是從110來表示的,數字越大線程的優先級越高。當沒有為一個線程設置優先級時,優先級默認為5 。但是對于子線程來說,它的優先級和父線程的優先級相同。

當需要對線程設置優先級時,我們可以通過調用setPriority()方法來設置,其語法格式如下:

public final void setPriority(int i);

其中參數i表示優先級的等級數,它可以從1到10.除了用數字表示優先級外,Java還在Thread類中定義了三個表示優先級的常量。MAX_PRIORITY表示線程的最高優先級,NORM_PRIORITY表示線程的默認優先級,MIN_PRIORITY表示線程的最低優先級。

yield讓步方法

在Java中具有兩種讓步方法,第一種就是yield讓步方法。yield讓步方法就是讓線程讓出當前占用的CPU,而將CPU讓給那一個線程是不確定的,需要由系統來決定。

注意:yield讓步操作可能不成功。因為線程中使用yield讓步方法后,線程進入準備狀態。但是系統可能再次選中該線程,使該線程再次進入運行狀態。

join讓步方法

join讓步方法的語法格式如下:

public final void join()throws InterruptedException;
public final void join(long mills) throws InterruptedException;
public final void join(long millis,int nanos) throws InterruptedException;

join讓步方法是具有三種形式的,沒有參數表示指定的線程執行完成后再執行其他線程;參數表示在參數的時間內執行讓步給的執行線程。

注意:join讓步方法也是可能發生捕獲異常的,所以在使用時要進行異常處理 。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容