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類(執行緒變數)
為每個執行緒變數建立一個該變數的副本,避免併發訪問的執行緒安全問題,保證執行緒安全