同步與異步
通常同步意味著一個任務的某個處理過程會對多個線程在用串行化處理,而異步則意味著某個處理過程可以允許多個線程同時處理。
異步通常代表著更好的性能,因為它很大程度上依賴于緩沖,是典型的使用空間換時間的做法,例如在計算機當中,高速緩存作為cpu和磁盤io之間的緩沖地帶協調cpu高速計算能力和磁盤的低速讀寫能力。
volatile
應用場景:檢查一個應用執行關閉或中斷狀態。因為此關鍵字拒絕了虛擬對一個變量多次賦值時的優化從而保證了虛擬機一定會檢查被該關鍵字修飾的變量的狀態變化。
CountDownLatch
應用場景:控制在一組線程操作執行完成之前當前線程一直處于等待。例如在主線程中執行await()方法阻塞主線程,在工作線程執行完邏輯后執行countDown()方法。
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class AsyncHandler {
/**
* 控制資源釋放.
*/
private CountDownLatch latch;
/**
* 處理完成標識.
*/
private volatile boolean handleFinish;
/**
* 消息寫入本地文件完成.
*/
private volatile boolean sendFinish;
/**
* 阻塞隊列.
*/
private BlockingQueue<Integer> queue;
public AsyncHandler(CountDownLatch latch){
this.latch = latch;
//使用鏈表實現.
queue = new LinkedBlockingQueue<Integer>();
}
public void handle() {
// 模擬性能瓶頸的執行過程,3s處理一條消息.
new Thread() {
public void run() {
while (!handleFinish) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e1) {
// 不做處理.
}
Integer number = queue.peek();
if (number != null) {
queue.poll();
System.out.println("write : "+number);
}
// 若隊列為空并且消息發送完成.
if (queue.isEmpty() && sendFinish) {
// 計數器1->0
latch.countDown();
// 讓處理過程結束.
handleFinish = true;
break;
}
}
}
}.start();
}
/**
* 給出消息發送完成的標識.
*/
public void sendFinish() {
System.out.println("send end sign !");
sendFinish = true;
}
/**
* 資源釋放.
*/
public void release() {
System.out.println("release!");
//清空隊列資源
if (queue != null) {
queue.clear();
queue = null;
}
}
/**
* 往隊列發送消息.
*/
public void sendMsg(Integer number) {
if (number != null) {
queue.add(number);
}
}
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
AsyncHandler handler = new AsyncHandler(latch);
handler.handle();
// 做一次檢查.
Scanner scanner = new Scanner(System.in);
while (true) {
Integer number = scanner.nextInt();
// 若用戶選擇退出.
if (-1 == number) {
// 表示消息已經發送完成.
handler.sendFinish();
break;
}
handler.sendMsg(number);
}
try {
// 阻塞主線程等待消息寫入到本地文件完成.
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 釋放資源 文件流,隊列.
handler.release();
// 關閉控制臺輸入.
scanner.close();
}
}