Java線程通信方法 0、(why)每個線程都有自己的棧空間,我們要線程之間進行交流,合作共贏。 1、synchronized和volatile關鍵字 a) 看下麵的synchronized關鍵字 b) 看下麵的volatile關鍵字 2、等待/通知機制:一個線程A調用對象的wait()方法,另一個 ...
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類(線程變數)
為每個線程變數創建一個該變數的副本,避免併發訪問的線程安全問題,保證線程安全