Java執行緒入門第二篇

布林bl發表於2018-12-24

Java執行緒通訊方法

0、(why)每個執行緒都有自己的棧空間,我們要執行緒之間進行交流,合作共贏。

1、synchronized和volatile關鍵字

  a) 看下面的synchronized關鍵字

  b) 看下面的volatile關鍵字

2、等待/通知機制:一個執行緒A呼叫物件的wait()方法,另一個執行緒呼叫執行緒B的notity()或者的notifyall()方法.

  a) 順序列印奇數偶數      

public class ThreadPrintDemo2 {

    public static void main(String[] args) {
        final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2();
        //java8新特性
        Thread t1 = new Thread(demo2 :: print1);
        Thread t2 = new Thread(demo2 :: print2);
        t1.start();
        t2.start();
    }
    public   synchronized void print2() {

        for (int i = 1; i <= 100; i +=2) {
            System.out.println(i);
            this.notify();  //通知等待中的程式
            try {
                this.wait();    //執行緒進入等待
                Thread.sleep(100);// 防止列印速度過快導致混亂
            } catch (InterruptedException e) {
                // NO
            }
        }
    }
    public synchronized void print1() {
        for (int i = 0; i <= 100; i += 2) {
            System.out.println(i);
            this.notify();  //通知等待中的程式
            try {
                this.wait();    //執行緒進入等待
                Thread.sleep(100);// 防止列印速度過快導致混亂
            } catch (InterruptedException e) {
                // NO
            }
        }
    }
}

複製程式碼

  b) 列印連續句子

public class ThreadPrintDemo2 {
    private char[] arr = new char[]{'a', ' ', 'b', 'c', 'd', 'e'};

    public static void main(String[] args) {
        final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2();
        Thread t1 = new Thread(demo2::print1);
        Thread t2 = new Thread(demo2::print2);
        t1.start();
        t2.start();
    }
    public synchronized void print2() {

        for (int i = 1; i < arr.length; i +=2) {
            System.out.print(arr[i]);
            this.notify();
            try {
                this.wait();
                Thread.sleep(100);// 防止列印速度過快導致混亂
            } catch (InterruptedException e) {
                // NO
            }
        }
    }
    public synchronized void print1() {
        for (int i = 0; i < arr.length; i +=2) {
            System.out.print(arr[i]);
            this.notify();
            try {
                this.wait();
                Thread.sleep(100);// 防止列印速度過快導致混亂
            } catch (InterruptedException e) {
                // NO
            }
        }
    }
}

複製程式碼

結果:a bcde

3、管道輸入輸出流:pipedreader和pipedwriter 面向字元

          Pipedoutputstream和pipedinputstream面向位元組

4、使用thread.join()方法:利用執行緒等待特性

5、使用ThreadLocal執行緒變數

Synchronize關鍵字(重量級鎖)

1、基礎:Java中每一個物件都可以作為鎖

2、手段:確保多執行緒在同一時刻,只有一個執行緒處於方法或同步塊中

3、實現原理:JVM基於進入和退出monitor物件來實現方法同步和程式碼塊同步

4、鎖優化:jdk1.6之後優化了鎖,加入了偏向鎖和輕量級鎖,鎖可以升級但不能降級

5、使用場景:方法 程式碼塊

Lock介面

在這裡插入圖片描述

1、他是一個介面

2、使用的時候需要顯式獲取鎖

3、使用方法:

Lock lock = new ReentrantLock();
lock.lock();
try {
    
}finally {
    lock.unlock();
}

複製程式碼

4、Synchronized經常與Lock放在一起比較

在這裡插入圖片描述

Volatile

1、是什麼:(what)是輕且量級的synchronize,保證共享變數的可見性(一個執行緒修改一個共享變數的時候,另一個執行緒會知道),並他不會引起執行緒的上下文切換和排程。

2、使用場景:修飾變數

3、優化:在1.7中將共享變數追加了60個位元組,變成64個位元組。因為(硬體)目前流行的cpu的快取記憶體行是64個位元組,當佇列的頭尾節點不足64位元組時候,處理器會將他們讀到同一個快取行,並且鎖定快取行。這樣會影響佇列出隊入隊效率。

ThreadLoacl類(執行緒變數)

為每個執行緒變數建立一個該變數的副本,避免併發訪問的執行緒安全問題,保證執行緒安全

相關文章