国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java多線程基礎(一)——線程與鎖

WelliJhon / 2562人閱讀

摘要:一線程的基本概念單線程簡單的說,單線程就是進程中只有一個線程。多線程由一個以上線程組成的程序稱為多線程程序。當線程調用完方法進入后會自動釋放鎖,線程獲得鎖。

一、線程的基本概念 1.1 單線程

簡單的說,單線程就是進程中只有一個線程。單線程在程序執行時,所走的程序路徑按照連續順序排下來,前面的必須處理好,后面的才會執行。

Java示例:

public class SingleThread {
    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            System.out.print(i + " ");
        }
    }
}

上述Java代碼中,只有一個主線程執行main方法。

1.2 多線程

由一個以上線程組成的程序稱為多線程程序。常見的多線程程序如:GUI應用程序、I/O操作、網絡容器等。
Java中,一定是從主線程開始執行(main方法),然后在主線程的某個位置啟動新的線程。

二、線程的基本操作 2.1 創建

Java中創建多線程類兩種方法:

1、繼承java.lang.Thread

Java示例:

public class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.print(i + " ");
        }
    }
}
public class MultiThread {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();    //啟動子線程
        //主線程繼續同時向下執行
        for (int i = 0; i < 10000; i++) {
            System.out.print(i + " ");
        }
    }
}

上述代碼中,MyThread類繼承了類java.lang.Thread,并覆寫了run方法。主線程從main方法開始執行,當主線程執行至t.start()時,啟動新線程(注意此處是調用start方法,不是run方法),新線程會并發執行自身的run方法。

2、實現java.lang.Runnable接口

Java示例:

public class MyThread implements Runnable {
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.print(i + " ");
        }
    }
}
public class MultiThread {
    public static void main(String[] args) {
        Thread t = new Thread(new MyThread());
        t.start();    //啟動子線程
        //主線程繼續同時向下執行
        for (int i = 0; i < 10000; i++) {
            System.out.print(i + " ");
        }
    }
}

上述代碼中,MyThread類實現了java.lang.Runnable接口,并覆寫了run方法,其它與繼承java.lang.Thread完全相同。實際上,java.lang.Thread類本身也實現了Runnable接口,只不過java.lang.Thread類的run方法主體里空的,通常被子類覆寫(override)。

注意:主線程執行完成后,如果還有子線程正在執行,程序也不會結束。只有當所有線程都結束時(不含Daemon Thread),程序才會結束。
2.2 暫停

Java中線程的暫停是調用java.lang.Thread類的sleep方法(注意是類方法)。該方法會使當前正在執行的線程暫停指定的時間,如果線程持有鎖,sleep方法結束前并不會釋放該鎖。

Java示例:

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.print(i + " ");
            try {
                Thread.sleep(1000);    //當前main線程暫停1000ms
            } catch (InterruptedException e) {
            }
        }
    }
}

上述代碼中,當main線程調用Thread.sleep(1000)后,線程會被暫停,如果被interrupt,則會拋出InterruptedException異常。

2.3 互斥

Java中線程的共享互斥操作,會使用synchronized關鍵字。線程共享互斥的架構稱為監視(monitor),而獲取鎖有時也稱為“持有(own)監視”。

每個鎖在同一時刻,只能由一個線程持有。
注意:synchronized方法或聲明執行期間,如程序遇到任何異常或return,線程都會釋放鎖。

1、synchronized方法

Java示例1:

//synchronized實例方法
public synchronized void deposit(int m) {
    System.out.print("This is synchronized method.");
}

注:synchronized實例方法采用this鎖(即當前對象)去做線程的共享互斥。

Java示例2:

//synchronized類方法
public static synchronized void deposit(int m) {
    System.out.print("This is synchronized static method.");
}

注:synchronized類方法采用類對象鎖(即當前類的類對象)去做線程的共享互斥。如上述示例中,采用類.class(繼承自java.lang.Class)作為鎖。

2、synchronized聲明
Java示例:

public void deposit(int m) {
    synchronized (this) {
        System.out.print("This is synchronized statement with this lock.");
    }
    synchronized (Something.class) {
        System.out.print("This is synchronized statement with class lock.");
    }
}

注:synchronized聲明可以采用任意鎖,上述示例中,分別采用了對象鎖(this)和類鎖(something.class)

2.4 中斷

java.lang.Thread類有一個interrupt方法,該方法直接對線程調用。當被interrupt的線程正在sleep或wait時,會拋出InterruptedException異常。
事實上,interrupt方法只是改變目標線程的中斷狀態(interrupt status),而那些會拋出InterruptedException異常的方法,如wait、sleep、join等,都是在方法內部不斷地檢查中斷狀態的值。

interrupt方法

Thread實例方法:必須由其它線程獲取被調用線程的實例后,進行調用。實際上,只是改變了被調用線程的內部中斷狀態;

Thread.interrupted方法

Thread類方法:必須在當前執行線程內調用,該方法返回當前線程的內部中斷狀態,然后清除中斷狀態(置為false) ;

isInterrupted方法

Thread實例方法:用來檢查指定線程的中斷狀態。當線程為中斷狀態時,會返回true;否則返回false。

2.5 協調

1、wait set / wait方法
wait set是一個虛擬的概念,每個Java類的實例都有一個wait set,當對象執行wait方法時,當前線程就會暫停,并進入該對象的wait set。
當發生以下事件時,線程才會退出wait set:
①有其它線程以notify方法喚醒該線程
②有其它線程以notifyAll方法喚醒該線程
③有其它線程以interrupt方法喚醒該線程
④wait方法已到期
注:當前線程若要執行obj.wait(),則必須先獲取該對象鎖。當線程進入wait set后,就已經釋放了該對象鎖。

下圖中線程A先獲得對象鎖,然后調用wait()方法(此時線程B無法獲取鎖,只能等待)。當線程A調用完wait()方法進入wait set后會自動釋放鎖,線程B獲得鎖。

2、notify方法
notify方法相當于從wait set中從挑出一個線程并喚醒。
下圖中線程A在當前實例對象的wait set中等待,此時線程B必須拿到同一實例的對象鎖,才能調用notify方法喚醒wait set中的任意一個線程。
注:線程B調用notify方法后,并不會立即釋放鎖,會有一段時間差。

3、notifyAll方法
notifyAll方法相當于將wait set中的所有線程都喚醒。

4、總結
wait、notify、notifyAll這三個方法都是java.lang.Object類的方法(注意,不是Thread類的方法)。
若線程沒有拿到當前對象鎖就直接調用對象的這些方法,都會拋出java.lang.IllegalMonitorStateException異常。

obj.wait()是把當前線程放到obj的wait set;

obj.notify()是從obj的wait set里喚醒1個線程;

obj.notifyAll()是喚醒所有在obj的wait set里的線程。

三、線程的狀態轉移

當創建一個Thread子類或實現Runnable接口類的實例時,線程進入【初始】狀態;

調用實例的start方法后,線程進入【可執行】狀態;

系統會在某一時刻自動調度處于【可執行】狀態的線程,被調度的線程會調用run方法,進入【執行中】狀態;

線程執行完run方法后,進入【結束】狀態;

處于【結束】狀態的線程,在某一時刻,會被JVM垃圾回收;

處于【執行中】狀態的線程,若調用了Thread.yield方法,會回到【可執行】狀態,等待再次被調度;

處于【執行中】狀態的線程,若調用了wait方法,會進入wait set并一直等待,直到被其它線程通過notify、notifyAll、interrupt方法喚醒;

處于【執行中】狀態的線程,若調用了Thread.sleep方法,會進入【Sleep】狀態,無法繼續向下執行。當sleep時間結束或被interrupt時,會回到【可執行狀態】;

處于【執行中】狀態的線程,若遇到阻塞I/O操作,也會停止等待I/O完成,然后回到【可執行狀態】;

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/71491.html

相關文章

  • 并發模型:線程與鎖

    摘要:文章結構來自七周七并發模型互斥和內存模型創建線程這段代碼創建并啟動了一個實例,首先從開始,函數的余下部分一起并發執行。在鎖定狀態下,某些線程擁有鎖在非鎖定狀態下,沒有線程擁有它。 并發&并行 并發程序含有多個邏輯上的獨立執行塊,他們可以獨立的并行執行,也可以串行執行。并行程序解決問題的速度比串行程序快的多,因為其可以同時執行整個任務的多個部分。并行程序可能有多個獨立執行塊,也可能只有一...

    JasinYip 評論0 收藏0
  • 并發編程

    摘要:一并發和并行并發是同一時間應對多件事情的能力并行是同一時間做多件事情的能力。用并發的目的,不僅僅是為了讓程序并行運行從而發揮多核的優勢。函數式編程函數式編程日漸重要的原因之一,是其對并發編程和并行編程提供了良好的支持。 一、并發和并行: 并發是同一時間應對(dealing with)多件事情的能力; 并行是同一時間做(doing)多件事情的能力。 二、并行架構: 位級并行,...

    Xufc 評論0 收藏0
  • BAT程序員必備技能

    摘要:前言想要進入等一線互聯網公司,以下是你必需具備的技能。包由解釋程序自動加載,不需要顯示說明。包包括許多具有特定功能的類,有日期向量哈希表堆棧等,其中類支持與時間有關的操作。包定義了應用程序編程接口,是應用程序環境的中性平臺組件結構。 前言 想要進入BAT等一線互聯網公司,以下是你必需具備的技能。如果你掌握的不牢固,那就趕快鞏固,如果你還沒有涉及,現在就立馬學習起來吧。 1.Java語言...

    fobnn 評論0 收藏0

發表評論

0條評論

WelliJhon

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<