本例用阻塞队列模拟一个异步处理的过程,代码如下
package add.asyn;
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;
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 ex){
throw new RuntimeException();
}
}
/*offer,add区别:
一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。
这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。
poll,remove区别:
remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似,
但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。
peek,element区别:
element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null*/
public void handle(){
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 ex){
//不做处理
}
}
//若队列为空 并且 消息发送完成
if(queue.isEmpty() && sendFinish){
latch.countDown(); //计数器1->0
handleFinish = true;
break;
}
}
}
}.start();
}
public void sendFinish(){ //给出消息返送完成的标识
sendFinish = true;
}
public void release(){ //释放资源
System.out.println("release!");
if(bw != null){
try {
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(queue != null){
queue.clear();
queue = null;
}
}
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();
}
}