標籤:
Java 非同步處理簡單實踐
http://www.cnblogs.com/fangfan/p/4047932.html
同步與非同步
通常同步意味著一個任務的某個處理過程會對多個線程在用序列化處理,而非同步則意味著某個處理過程可以允許多個線程同時處理。
非同步通常代表著更好的效能,因為它很大程度上依賴於緩衝,是典型的使用空間換時間的做法,例如在電腦當中,快取作為cpu和磁碟io之間的緩衝地帶協調cpu高速計算能力和磁碟的低速讀寫能力。
volatile
應用情境:檢查一個應用執行關閉或中斷狀態。因為此關鍵字拒絕了虛擬對一個變數多次賦值時的最佳化從而保證了虛擬機器一定會檢查被該關鍵字修飾的變數的狀態變化。
CountDownLatch
應用情境:控制在一組線程操作執行完成之前當前線程一直處於等待。例如在主線程中執行await()方法阻塞主線程,在背景工作執行緒執行完邏輯後執行countDown()方法。
本文樣本情境:
1,從控制台發送訊息到Message Service器(由一個隊列類比)。
2,將訊息佇列寫入到檔案(對寫檔案的操作設定延時以類比效能瓶頸)。
3,Message Service器作為控制台和檔案寫入之間的緩衝區。
範例程式碼:
註:往訊息佇列添加訊息可以通過for迴圈一次性加入,本文為了便於觀察檔案和隊列的變化而採用了控制台輸入,實際寫一行檔案記錄速度應該高於手速,所以本文樣本中增加了線程sleep時間。
package org.wit.ff.ch2;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;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;/** * * <pre> * 簡單非同步處理樣本. * </pre> * * @author F.Fang * @version $Id: AsyncHandler.java, v 0.1 2014年10月23日 下午11:37:54 F.Fang Exp $ */public class AsyncHandler { /** * 控制資源釋放. */ private CountDownLatch latch; /** * 處理完成標識. */ private volatile boolean handleFinish; /** * 訊息寫入本地檔案完成. */ private volatile boolean sendFinish; /** * 阻塞隊列. */ private BlockingQueue<String> queue; private BufferedWriter bw; public AsyncHandler(CountDownLatch latch) { this.latch = latch; /** * 使用鏈表實現. */ queue = new LinkedBlockingQueue<String>(); File file = new File("E:/hello.txt"); try { bw = new BufferedWriter(new FileWriter(file)); } catch (IOException e) { throw new RuntimeException(e); } } public void handle() { // 類比效能瓶頸的執行過程,3s處理一條訊息. new Thread() { public void run() { while (!handleFinish) { try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e1) { // 不做處理. } String s = queue.peek(); if (s != null) { queue.poll(); try { bw.write(s); bw.newLine(); } catch (IOException e) { } } // 若隊列為空白並且訊息發送完成. if (queue.isEmpty() && sendFinish) { // 計數器1->0 latch.countDown(); // 讓處理過程結束. handleFinish = true; break; } } } }.start(); } /** * * <pre> * 給出訊息發送完成的標識. * </pre> * */ public void sendFinish() { sendFinish = true; } /** * * <pre> * 資源釋放. * </pre> * */ public void release() { System.out.println("release!"); if (bw != null) { try { bw.close(); } catch (IOException e) { // TODO 列印日誌. } } //其實使用queue = null就夠了. if (queue != null) { queue.clear(); queue = null; } } /** * * <pre> * 往隊列發送訊息. * </pre> * * @param text */ public void sendMsg(String text) { if (text != null && !text.isEmpty()) { queue.add(text); } } 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) { String text = scanner.next(); // 若使用者選擇退出. if ("exit".equals(text)) { // 表示訊息已經發送完成. handler.sendFinish(); break; } handler.sendMsg(text); } try { // 阻塞主線程等待訊息寫入到本地檔案完成. latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } // 釋放資源 檔案流,隊列. handler.release(); // 關閉控制台輸入. scanner.close(); }}
Java 非同步處理簡單實踐