环形缓冲区(JAVA数组实现)


1. ///
2. /// 写了个小玩意 — ascii字符“播放器“,其实也只需要解决个缓冲问题,         ///
3. /// 因我很无耻地认为这个环形缓冲还有其它用武之地,                        ///
4. /// 于是贴上来了。 接受考验~ 请不吝BS~                                  ///
5. /// main方法只是个使用例子,可以删除之。                                 ///
6. ///
7. package
8.   
9. import
10. import
11. import
12. import
13. import
14.   
15. /**
16.  * 环形缓冲区(数组实现),逻辑上缓冲区是首位衔接着,像个圆圈一样。
17.  * 
18.  * @author Cupenoruler@foxmail.com
19.  * @version 2011-11-22
20.  */
21. public class
22.       
23. private Object[] buffer = null; // 数据容器 
24. private int capacity    = 0;    // 缓冲区长度 
25. private int indexForPut = 0;    // put索引 (下一个要写入的位置)
26. private int indexForGet = 0;    // get索引 (下一个要读取的位置)
27.       
28. /* put 和 get 的线程状态标记 */
29. private
30. private
31.       
32. /*************************************************\
33.      *            仅作测试之用,可删除此方法          *
34.      * 小子这里仅有6000多个txt文本,基本凑合  *
35.     \************************************************/
36. public static void
37.           
38. //拿到源文件列表
39. "D:/Backup/workbench/ASCII_Player/resource/txt";  
40. final File[] fileSource = new
41.           
42. final CircularBuffer<String> cBuffer = new CircularBuffer<String>(2048);  
43.           
44. //专业的读文本线程
45.         Thread putThread =   
46. new
47. public void
48. new StringBuilder(4096); //文本缓冲
49. null;  
50. null;  
51.                       
52. try
53. /* 挨个读取文本 */
54. for(File temp : fileSource) {  
55. 0, tempBuilder.length()); //清空builder 
56. new BufferedReader( new
57.                               
58. while( null
59.                                 tempBuilder.append(tempString);  
60. "\n");  
61.                             }  
62. //build完成,入库
63.                         }  
64. //读完收工
65.                           
66. catch
67.                         e.printStackTrace();  
68. "文件不存在,txtsPath可能有误");  
69.                       
70. catch
71.                         e.printStackTrace();  
72. "tempReader挂球");  
73.   
74.                     }  
75. //put线程标记为:完成
76.                 }  
77.             };  
78.           
79. /* 开动put线程………………  */
80.         putThread.start();  
81.           
82. /* get线程(当前线程 ) */
83. while(true){  
84.             String temp = cBuffer.getElement();  
85. if(temp == null){   
86. break;  
87. else
88.                 System.out.println(temp);  
89.             }  
90.               
91. try
92. 20);  
93. catch
94.                 e.printStackTrace();  
95.             }  
96.         }  
97.     }  
98.       
99. /**
100.      * 指定长度的缓冲区
101.      * @param capacity
102.      */
103. public CircularBuffer(int
104. this.capacity = capacity;  
105. this.buffer = new String[this.capacity];  
106.     }  
107.   
108. <pre name="code" class="java">    /**
109.      * 写入数据,注意此函数会导致阻塞
110.      * @param element
111.      */
112. public void
113. // 有空位就插入~
114. // 没空位就轮询,直到有空位可插入为止~
115. while (null != this.buffer[this.indexForPut]) {  
116. try
117. this.setPutThreadState(ThreadState.BLOCK); // put线程标记为:阻塞
118. 100);  
119.   
120. catch
121. // 例行公事
122. "线程意外停止,正在检查");  
123.               
124.             }  
125.         }  
126. this.setPutThreadState(ThreadState.RUNNING); // put线程标记为:正在运行
127.           
128. // 填入元素,将put索引指向下一元素位~
129. this.buffer[this.indexForPut] = element;  
130. this.indexForPut++;  
131. this.indexForPut %= this.capacity;  
132.     }  
133.   
134. /**
135.      * 取数据,注意此函数会阻塞,若put线程结束且缓冲区为空时函数会返回null
136.      * @return 下一个T元素  或者 null
137.      */
138. @SuppressWarnings("unchecked")  
139. public
140. // 有元素就拿出~
141. // 没元素就轮询,直到有元素可拿为止~ 若是put完毕、 数据取空,则返回null以告知调用者 
142. while (null == this.buffer[this.indexForGet]) {  
143. try
144. this.setGetThreadState(ThreadState.BLOCK); // get线程标记为:阻塞       
145. if( this.isPutedOver()&& this.isEmputy() ){  
146. this.setGetThreadState(ThreadState.OVER);  
147. return null;  
148.                 }  
149. 100);  
150.   
151. catch
152.                 e.printStackTrace();  
153. "线程意外停止");  
154.   
155.             }  
156.         }  
157. this.setGetThreadState(ThreadState.RUNNING); // get线程标记为:正在运行
158.           
159. /* 拿到元素,buffer腾出该元素位,将get索引指向下一元素~ */
160. this.buffer[this.indexForGet];  
161. this.buffer[this.indexForGet] = null;  
162. this.indexForGet++;  
163. this.indexForGet %= this.capacity;  
164.   
165. return (T)temp; // 返回拿到的元素引用
166.     }  
167.   
168. /****************************************************\
169.      *           --Setter and Getter--                  *
170.     \****************************************************/
171. /**
172.      * 检查此环形缓冲区是否为空 
173.      * @return boolean true则表示为空,false则不为空
174.      */
175. public boolean
176. // 新元素是以 索引0 向 索引length 的顺序 put入
177. // 有鉴于此,这里倒过来枚举,防止出现“同向追赶”导致落空的的囧事;
178. for(int i = this.buffer.length-1; i > 0; i--){  
179. if( this.buffer[i] != null
180. return false;  
181.             }  
182.         }  
183. return true;  
184.     }  
185.       
186. /**
187.      * 检查 put 线程和 get 线程是否同时阻塞,
188.      * @return boolean true-挂球  false-良好
189.      */
190. public boolean
191. return ( this.getThreadState == ThreadState.BLOCK  
192. this.putThreadState == ThreadState.BLOCK );  
193.     }  
194.       
195. /**
196.      * 检查数据源是否缓冲完毕
197.      * @return boolean true-完成  false-未完成
198.      */
199. public boolean
200. return  this.putThreadState == ThreadState.OVER;  
201.     }  
202.   
203. public void
204. this.putThreadState = putThreadState;  
205.     }  
206.   
207. private void
208. this.getThreadState = getThreadState;  
209.     }  
210.   
211. }  
212.   
213. /**
214.  * 线程的几种状态
215.  * @author Cupenoruler@foxmai.com
216.  * @version 2011-11-22
217.  */
218. enum
219. /*暂时阻塞*/
220. /*运行*/
221. /*线程顺利完成*/
222. /*中断,(暂时用不到)*/
223. }