通常同步意味著一個任務的某個處理過程會對多個線程在用串行化處理,而異步則意味著某個處理過程可以允許多個線程同時處理。下面我們就來看看有關異步處理的詳細內容。
異步通常代表著更好的性能,因為它很大程度上依賴于緩沖,是典型的使用空間換時間的做法,例如在計算機當中,高速緩存作為cpu和磁盤io之間的緩沖地帶協調cpu高速計算能力和磁盤的低速讀寫能力。
volatile
應用場景:檢查一個應用執行關閉或中斷狀態。因為此關鍵字拒絕了虛擬對一個變量多次賦值時的優化從而保證了虛擬機一定會檢查被該關鍵字修飾的變量的狀態變化。
CountDownLatch
應用場景:控制在一組線程操作執行完成之前當前線程一直處于等待。例如在主線程中執行await()方法阻塞主線程,在工作線程執行完邏輯后執行countDown()方法。
本文示例場景:
1,從控制臺發送消息到消息服務器(由一個隊列模擬)。
2,將消息隊列寫入到文件(對寫文件的操作設置延時以模擬性能瓶頸)。
3,消息服務器作為控制臺和文件寫入之間的緩沖區。
示例代碼:
注:往消息隊列添加消息可以通過for循環一次性加入,本文為了便于觀察文件和隊列的變化而采用了控制臺輸入,實際寫一行文件記錄速度應該高于手速,所以本文示例中增加了線程sleep時間。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
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(); } } |
總結
以上就是本文關于異步機制的全部內容,實例代碼中的注釋還是比較詳細的,如果有什么問題可以留言,小編會及時回復大家。同時也感謝大家對本站的支持!
原文鏈接:http://www.cnblogs.com/fangfan/p/4047932.html