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

資訊專欄INFORMATION COLUMN

Java 并發(fā)學(xué)習(xí)筆記(二)

zgbgx / 2306人閱讀

摘要:請(qǐng)參看前一篇文章并發(fā)學(xué)習(xí)筆記一原子性可見(jiàn)性有序性問(wèn)題六等待通知機(jī)制什么是等待通知機(jī)制當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài)如果線程滿足要求的某個(gè)條件后,則通知等待的線程重新執(zhí)行。經(jīng)極客時(shí)間并發(fā)編程實(shí)戰(zhàn)專欄內(nèi)容學(xué)習(xí)整理

請(qǐng)參看前一篇文章:Java 并發(fā)學(xué)習(xí)筆記(一)——原子性、可見(jiàn)性、有序性問(wèn)題

六、等待—通知機(jī)制

什么是等待通知—機(jī)制?當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài);如果線程滿足要求的某個(gè)條件后,則通知等待的線程重新執(zhí)行。

等待通知機(jī)制的流程一般是這樣的:線程首先獲取互斥鎖,當(dāng)不滿足某個(gè)條件的時(shí)候,釋放互斥鎖,并進(jìn)入這個(gè)條件的等待隊(duì)列;一直等到滿足了這個(gè)條件之后,通知等待的線程,并且需要重新獲取互斥鎖。

1. 等待-通知機(jī)制的簡(jiǎn)單實(shí)現(xiàn)

等待-通知機(jī)制可以使用 Java 的 synchronized 關(guān)鍵字,配合 wait()、notify()、notifyAll() 這個(gè)三個(gè)方法來(lái)實(shí)現(xiàn)。

前面說(shuō)到的解決死鎖問(wèn)題的那個(gè)例子,一次性申請(qǐng)所有的資源,使用的是循環(huán)等待,這在并發(fā)量很大的時(shí)候比較消耗 CPU 資源。

現(xiàn)在使用等待-通知機(jī)制進(jìn)行優(yōu)化:

final class Monitor {
    
    private List res = new ArrayList<>(2);
    
    /**
     * 一次性申請(qǐng)資源 
     */
    public synchronized void apply(Object resource1, Object resource2) {
        while (res.contains(resource1) || res.contains(resource2)){
            try {
                //條件不滿足則進(jìn)入等待隊(duì)列
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        res.add(resource1);
        res.add(resource2);
    }
    /** 
     * 歸還資源 
     */
    public synchronized void free(Object resource1, Object resource2){
        res.remove(resource1);
        res.remove(resource2);
        //釋放資源之后,通知等待的線程開(kāi)始執(zhí)行
        this.notifyAll();
    }
}
2. 需要注意的地方

1) 每個(gè)互斥鎖都有相應(yīng)的等待隊(duì)列,例如上面的例子,就存在兩個(gè)等待隊(duì)列,一是 synchronized 入口等待隊(duì)列,二是 while 循環(huán)這個(gè)條件的等待隊(duì)列。

2) 調(diào)用 wait() 方法,會(huì)使當(dāng)前線程釋放持有的鎖,并進(jìn)入這個(gè)條件的等待隊(duì)列。滿足條件之后,隊(duì)列中的線程被喚醒,不是馬上執(zhí)行,而是需要重新獲取互斥鎖。例如上圖中,if 條件的隊(duì)列中的線程被喚醒后,需要重新進(jìn)入 synchronized 處獲取互斥鎖。

3. wait 和 sleep 的區(qū)別

相同點(diǎn):兩個(gè)方法都會(huì)讓渡 CPU 的使用權(quán),等待再次被調(diào)度。

不同點(diǎn):

wait 屬于 Object 的方法,sleep 是 Thread 的方法

wait 只能在同步方法或同步塊中調(diào)用,sleep 可以在任何地方調(diào)用

wait 會(huì)釋放線程持有的鎖,sleep 不會(huì)釋放鎖資源

七、管程理論
1. 什么是管程?

指的是對(duì)共享變量和對(duì)共享變量的操作的管理,使其支持并發(fā),對(duì)應(yīng)到 Java,指的是管理類的成員變量和方法,讓這個(gè)類是線程安全的。

2. 管程模型

管程主要的模型有 Hasen、Hoare、MESA ,其中 MESA 最常用。管程的 MESA 模型主要解決的是線程的互斥和同步問(wèn)題,和上面說(shuō)到的等待-通知機(jī)制十分類似。示意圖如下:

首先看看管程是如何實(shí)現(xiàn)互斥的?在管程的入口有一個(gè)等待隊(duì)列,一次只允許一個(gè)線程進(jìn)入管程。每個(gè)條件對(duì)應(yīng)一個(gè)等待隊(duì)列,當(dāng)線程不滿足條件的時(shí)候,進(jìn)入對(duì)應(yīng)的等待隊(duì)列;當(dāng)條件滿足的時(shí)候,隊(duì)列中的線程被喚醒,重新進(jìn)入到入口處的等待隊(duì)列獲取互斥鎖,這就實(shí)現(xiàn)了線程的同步問(wèn)題。

3. 管程的最佳實(shí)踐

接下來(lái)使用代碼實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的阻塞隊(duì)列,這就是一個(gè)很典型的管程模型,解決了線程互斥和同步問(wèn)題。

public class BlockingQueue {
    private int capacity;
    private int size;

    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    /**
     * 入隊(duì)列
     */
    public void enqueue(T data){
        lock.lock();
        try {
            //如果隊(duì)列滿了,需要等待,直到隊(duì)列不滿
            while (size >= capacity){
                notFull.await();
            }
            //入隊(duì)代碼,省略
            //入隊(duì)之后,通知隊(duì)列已經(jīng)不為空了
            notEmpty.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 出隊(duì)列
     */
    public T dequeue(){
        lock.lock();
        try {
            //如果隊(duì)列為空,需要等待,直到隊(duì)列不為空
            while (size <= 0){
                notEmpty.await();
            }
            //出隊(duì)代碼,省略
            //出隊(duì)列之后,通知隊(duì)列已經(jīng)不滿了
            notFull.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        //實(shí)際應(yīng)該返回出隊(duì)數(shù)據(jù)
        return null;
    }
}
八、Java 中的線程
1. 線程的生命周期

Java 中的線程共分為了 6 種狀態(tài),分別是:

NEW(初始化狀態(tài))

RUNNABLE(可運(yùn)行/運(yùn)行狀態(tài))

BLOCKED(阻塞狀態(tài))

WAITING(無(wú)限時(shí)等待)

TIMED_WAITING(限時(shí)等待)

TERMINATED(終止?fàn)顟B(tài))

2. 線程狀態(tài)轉(zhuǎn)換

RUNNABLE 與 BLOCKED 狀態(tài)的轉(zhuǎn)換:在線程等待 synchronized 的鎖時(shí),會(huì)進(jìn)入 BLOCKED 狀態(tài),當(dāng)獲取到鎖之后,又轉(zhuǎn)換到 RUNNABLE 狀態(tài)。

RUNNABLE 與 WAITING 狀態(tài)的轉(zhuǎn)換:1) 線程獲取到 synchronized 鎖之后,并且調(diào)用了 wait() 方法。 2) 調(diào)用 Thread.join() 方法,例如線程 A 調(diào)用 join() 方法,線程 B 等待 A 執(zhí)行完畢,等待期間 B 進(jìn)入 WAITING 狀態(tài),線程 A 執(zhí)行完后,線程 B 切換到 RUNNABLE 狀態(tài)。3) 調(diào)用 LockSupport.park() 方法

RUNNABLE 與 TIMED_WAITING 狀態(tài)的轉(zhuǎn)換:以上三種情況,分別在方法中加上超時(shí)參數(shù)即可。另外還有兩種情況:Thread.sleep(long millis) 方法,LockSupprt.parkNanos(Object blocker, long deadline)。

NEW 到 RUNNABLE 狀態(tài)的轉(zhuǎn)換:在 Java 中新創(chuàng)建的線程,會(huì)立即進(jìn)入 NEW 狀態(tài),然后啟動(dòng)線程進(jìn)入 RUNNABLE 狀態(tài)。Java 中新建線程一般有三種方式:

繼承 Thread 類

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("I am roseduan");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

實(shí)現(xiàn) Runnable 接口,并將其實(shí)現(xiàn)類傳給 Thread 作為參數(shù)

public class MyThread {

    public static void main(String[] args) {
        Thread thread = new Thread(new Print());
        thread.start();
    }
}

class Print implements Runnable{
    @Override
    public void run() {
        System.out.println("I am roseduan");
    }
}

實(shí)現(xiàn) Collable 接口,將其實(shí)現(xiàn)類傳給線程池執(zhí)行,并且可以獲取返回結(jié)果

public class ThreadTest {

    public static void main(String[] args) throws InterruptedException {
        //線程池
        BlockingQueue queue = new LinkedBlockingQueue<>(5);
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 1,
                TimeUnit.HOURS, queue);
        //執(zhí)行
        Future submit = threadPool.submit(new Demo());
    }
}

class Demo implements Callable {

    @Override
    public String call() {
        System.out.println("I am roseduan");
        return "I am roseduan";
    }
}

NEW 到 TERMINATED 狀態(tài)的轉(zhuǎn)換:線程執(zhí)行完 run() 方法后,會(huì)自動(dòng)切換到 TERMINATED 狀態(tài)。如果手動(dòng)中止線程,可以使用 interrupt() 方法。

3. 局部變量的線程安全性

局部變量存在于方法中,每個(gè)方法都有對(duì)應(yīng)的調(diào)用棧幀,由于每個(gè)線程都有自己獨(dú)立的方法調(diào)用棧,因此局部變量并沒(méi)有被共享。所以即便多個(gè)線程同時(shí)調(diào)用同一個(gè)方法,方法內(nèi)部的局部變量也是線程安全的,不需要多帶帶加鎖。

經(jīng)極客時(shí)間《Java 并發(fā)編程實(shí)戰(zhàn)》專欄內(nèi)容學(xué)習(xí)整理

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/77718.html

相關(guān)文章

  • 后臺(tái)開(kāi)發(fā)常問(wèn)面試題集錦(問(wèn)題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問(wèn)題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問(wèn)題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    spacewander 評(píng)論0 收藏0
  • 后臺(tái)開(kāi)發(fā)常問(wèn)面試題集錦(問(wèn)題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問(wèn)題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問(wèn)題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    xfee 評(píng)論0 收藏0
  • 后臺(tái)開(kāi)發(fā)常問(wèn)面試題集錦(問(wèn)題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問(wèn)題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問(wèn)題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    makeFoxPlay 評(píng)論0 收藏0
  • 四年來(lái)Android面試大綱,作為一個(gè)Android程序員

    摘要:再附一部分架構(gòu)面試視頻講解本文已被開(kāi)源項(xiàng)目學(xué)習(xí)筆記總結(jié)移動(dòng)架構(gòu)視頻大廠面試真題項(xiàng)目實(shí)戰(zhàn)源碼收錄 Java反射(一)Java反射(二)Java反射(三)Java注解Java IO(一)Java IO(二)RandomAccessFileJava NIOJava異常詳解Java抽象類和接口的區(qū)別Java深拷貝和淺拷...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

zgbgx

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<