使用阻塞式线程安全列表
2.使用阻塞式线程安全列表
阻塞式列表与非阻塞式列表的主要区别是:阻塞式列表在插入和删除操作时,如果列表已经满或者已经空了的话,操作不会被立即执行。
而是将调用换这个操作的线程阻塞
直到操作可以执行成功。
本节使用LinkedBlockingDeque类来实现阻塞式列表。
使用方法:
take():从列表中取出字符串,如果列表为空,调用这个方法将被阻塞到列表不为空(即有可用元素)
put():将字符串插入列表中,如果列表已经满(列表生成时指定了固定的容量),调用这个方法的线程将被阻塞直到列表中有可用的元素。
takeFirst(),takeLast():分别返回列表中第一个和最后一个元素,返回的元素会从列表中移除。如果列表为空,
调用方法的线程将被阻塞直到列表中有可用的元素出现。
getFirst(),getLast():分别返回列表中第一个和最后一个元素,返回的元素不会从列表中移除。如果列表为空的话,则抛出NoSuchElementException异常。
peek(),peekFirst(),peekLast():分别返回列表中一个和最后一个元素,返回的元素不会从列表中移除,如果列表为空,返回null。
poll(),pollFirst(),pollLast():分别返回列表中第一个和最后一个元素,返回的元素会从列表中移除,如果列表为空,返回null。
add(),addFirst(),addLast():分别将元素添加到列表中的第一位和最后一位。如果列表已经满,这些方法静抛出IllegalStateException异常。
实例代码:
/**
*
* @author fcs
* @date 2015-6-21
* 描述:使用阻塞式线程安全列表
* 说明:添加大量的数据到一个列表中
*
* 本类使用put()方法将字符串插入到列表中,如果列表(列表生成时指定了容量)已经满的话
* 调用该方法的线程将被阻塞直到列表中有了可用的空间。
*
*/
public class Client implements Runnable {
private LinkedBlockingDeque<String> requestList;
public Client(LinkedBlockingDeque<String> requestList) {
this.requestList = requestList;
}
@Override
public void run() {
for(int i =0;i<3;i++){
for(int j =0 ;i< 5;j++){
StringBuilder request = new StringBuilder();
request.append(i);
request.append(":");
request.append(j);
try {
requestList.put(request.toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Client: %s at %s.\n",request,new Date());
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
*
* @author fcs
* @date 2015-6-23
* 描述:该类使用take()方法从列表中取出字符串,如果列表为空,调用这个方法的线程将阻塞直到列表不为空(即有可用元素)
* 说明:调用这两个方法的线程可能被阻塞,在阻塞是如果线程被中断,方法会抛出InterruptedException异常。
* 所以必须捕获和处理异常。
*/
public class Main {
public static void main(String[] args) {
LinkedBlockingDeque<String> list = new LinkedBlockingDeque<String>(3);
Client client = new Client(list);
Thread thread = new Thread(client);
thread.start();
for(int i =0;i<5;i++){
for(int j =0;j<3;j++){
try {
String request = list.take();
System.out.printf("Main: request: %s at %s. Size: %d\n",request,new Date(),list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Main : End of the program.");
}
}
运行结果