`
hz_chenwenbiao
  • 浏览: 996095 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

阻塞队列使用---ArrayBlockingQueue(转)

阅读更多

 

ArrayBlockingQueue是JAVA5中的一个阻塞队列,能够自定义队列大小,当插入时,如果队列已经没有空闲位置,那么新的插入线程将阻塞到该队列,一旦该队列有空闲位置,那么阻塞的线程将执行插入。从队列中取数据为:take,放数据为:put。下面的例子模拟了两个队列的插入和获取,首先在队列2中插入一个数据,启动线程2向队列2中插入数据时,该线程将阻塞在队列2等待,同时启动线程1向队列1中插入数据,由于队列1此时为空那么能够正确插入,然后从队列2中取数据,当线程1再次插入时,阻塞到队列1,此时,阻塞在队列2的线程2能够插入,并且从队列1中取数据,此时线程1能够插入,如此往复50次,并且每次插入成功后都循环输出10次。代码如下:

 import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;
 
public class ArrayBlockingCommunication {
 
    public static void main(String[] args) {
         
        final Business business = new Business();
         
        new Thread(new Runnable(){
 
            public void run() {
                for(int i=0; i<50; i++){
                    business.sub(i);
                }
            }
             
        }).start();
         
         
        new Thread(new Runnable(){
 
            public void run() {
                for(int i=0; i<50; i++){
                    business.main(i);
                }
            }
             
        }).start();
         
    }
     
     
     
    static class Business{
         
        BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1);
        BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1);
 
        {
            try{
                queue2.put(1);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
         
        public void sub(int i){
             
             
            try {
                queue1.put(1);
                System.out.println("线程" + Thread.currentThread().getName() + 
                "正在阻塞");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("线程" + Thread.currentThread().getName() + 
            "开始运行");
            for(int j=1; j<=10; j++){
                System.out.println("sub thread sequence is " + j + " loop of " + i);
            }
            try {
                queue2.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         
         
         
        public void main(int i){
             
            try {
                queue2.put(1);
                System.out.println("线程" + Thread.currentThread().getName() + 
                        "正在阻塞");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程" + Thread.currentThread().getName() + 
            "开始运行");
            for(int j=1; j<=10; j++){
                System.out.println("main thread sequence is " + j + " loop of " + i);
            }
            try {
                queue1.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
}

 

 

 

请大家注意:在Business类中有一个匿名构造函数,其特点如下:

匿名构造方法,在任何构造方法之前被调用。这样保证我们初始化Business类时已经向队列2中插入了数据,这样执行起来保证我们看到的线程1先运行,然后是线程2。

 

载自:http://www.cnblogs.com/belen/archive/2012/04/13/2446019.html


阻塞队列是也就是一个普通的队列,只是使用的场合是多线程的情况下使用的,当队列没东西时,进程会阻塞,每个进程从队列取自己想要的东西,互相不会取同一个东西。

 

 

BlockingQueue接口定义的所有方法实现都是线程安全的,它的实现类里面都会用锁和其他控制并发的手段保证这种线程安全,但是这些类同时也实现了Collection接口(主要是AbstractQueue实现),所以会出现BlockingQueue的实现类也能同时使用Conllection接口方法,而这时会出现的问题就是像addAll,containsAll,retainAll和removeAll这类批量方法的实现不保证线程安全,举个例子就是addAll 10个items到一个ArrayBlockingQueue,可能中途失败但是却有几个item已经被放进这个队列里面了。

 

更详细见:

并发容器——BlockingQueue相关类

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics