使用LinkedList实现安全队列

         使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。 

        

/**
 * 使用LinkedList实现安全队列
 *
 */
public class SafeLinkedList<E> {

    private LinkedList<E> data = new LinkedList<>();
    private int totalSize;

    public SafeLinkedList(int totalSize) {
        this.totalSize = totalSize;

    }

    /**
     * 当队列已满时候,阻塞,直到取走数据为止
     * @param e
     */
    public void add(E e) {
        synchronized (data) {
            if (data.size() == totalSize) {
                try {
                    data.wait();
                } catch (InterruptedException e1) {
                    Thread.interrupted();
                    data.notifyAll();
                    System.out.println("队列已满啦!");
                }

            }
            data.add(e);
            data.notifyAll();

        }

    }

    /**
     * 当队列为空时候,阻塞等待
     * @return
     */
    public E get() {
        synchronized (data) {

            if (data.isEmpty()) {
                try {
                    data.wait();
                } catch (InterruptedException e) {
                    Thread.interrupted();
                    data.notifyAll();
                }
            }

            E e = data.getFirst();//获取队列头元素
            data.removeFirst();//移除对头元素
            data.notifyAll();
            return e;
        }
    }

    public synchronized int size() {
        return data.size();
    }
}

测试队列:

/**
 * 多线程条件下测试LinkedList存取数据是否安全
 */
public class SafeLinkedListTest {

    private SafeLinkedList<String> data = new SafeLinkedList<>(10);

    @Test
    public void putGetTest() throws InterruptedException {

        //add test
        Thread t1 = new Thread(new OperAddThread());
        Thread t2 = new Thread(new OperAddThread());
        Thread t3 = new Thread(new OperAddThread());

        Thread getThread = new Thread(new OperGetThread());
        getThread.setName("getThread");

        t1.start();
        t2.start();
        t3.start();
        getThread.start();

        t1.join();
        t2.join();
        t3.join();
        getThread.join();

        System.out.println(data.size());

    }

    class OperAddThread implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 4; i++) {
                String addData=Thread.currentThread().getName()+"|"+String.valueOf(i);
                data.add(addData);
                System.out.println("add size=" + data.size());
                System.out.println(Thread.currentThread().getName() + " addData=" + addData);
            }
        }
    }

    class OperGetThread implements Runnable {
        @Override
        public void run() {
            int i=11;
            while (i>=0) {
                i--;
                String value = data.get();
                System.out.println("get size=" + data.size());
                System.out.println("get string--" + " ;value=" + value);
            }
        }
    }
}
时间: 2024-10-22 23:09:24

使用LinkedList实现安全队列的相关文章

java LinkedList类实现 队列

  /* LinkedList 类实现队列 队列 是FIFO  先进先出 FIRST  IN  FIRST OUT      一边进去 另一边出来 LinkedList 底层是采用链表完成 ArrayList底层采用数组完成 对数据的查找操作 用数组更快 */ import java.util.LinkedList; class  MyQueue {  private LinkedList ll=new LinkedList();  void put(Object o)  {   ll.addL

解析Java中的队列和用LinkedList集合模拟队列的方法_java

API中对队列的说明:   public interface Queue<E> extends Collection<E> 在处理元素前用于保存元素的 collection.除了基本的 Collection 操作外,队列还提供其他的插入.提取和检查操作.每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作).插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的:在大多数实现中,插入操作不会失败. 队列通常

Java 容器 &amp; 泛型:二、ArrayList 、LinkedList和Vector比较

一.List回顾 序列(List),有序的Collection,正如它的名字一样,是一个有序的元素列表.确切的讲,列表通常允许满足 e1.equals(e2) 的元素对 e1 和 e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素.实现List的有:ArrayList.LinkedList.Vector.Stack等.值得一提的是,Vector在JDK1.1的时候就有了,而List在JDK1.2的时候出现,待会我们会聊到ArrayList和Vector的区别.  

新人求教队列和栈的存取问题/xl

问题描述 以下都是什么意思啊?1.队列队头.forward.back2.栈顶.forward.back3.栈顶.back.forward 解决方案 解决方案二:队列FIFOfirstinfirstout先进先出栈FILOfirstinlastout先进后出楼主的问题,不明白解决方案三: 解决方案四:断开QHead.forward向后的链接让QHead指向QHead.forward解决方案五:你这是自己封装了一个双向链表的结构,每一个节点包含数据,前一节点和后一节点.通过forward和back可

TIJ阅读笔记(第十一章)

笔记 11:对象的集合  如果程序的对象数量有限,且寿命可知,那么这个程序是相当简单的.数组  数组与其它容器的区别体现在三个方面:效率,类型识别以及可以持有primitives.数组是Java提供的,能随机存储和访问reference序列的诸多方法中的,最高效的一种.数组是一个简单的线性序列,所有它可以快速的访问其中的元素.但是速度是有代价的:当你创建了一个数组之后,它的容量就固定了,而且在其生命周期里不能改变.也许你会提议先创建一个数组,等到快不够用的时候,再创建一个新的,然后将旧的数组里的

《Android 3D 游戏案例开发大全》——6.6节游戏界面相关类

6.6 游戏界面相关类 Android 3D 游戏案例开发大全 前一小节为读者介绍了辅助界面相关类,本小节将对游戏界面相关类进行介绍,首先介绍游戏界面的各个组成部分,然后介绍游戏整体界面的开发,逐步完成对游戏界面的开发,下面就对这些类的开发进行详细介绍. 6.6.1 顶点数据管理者VertexDataManager 本小节为读者介绍的是整个游戏过程中所有物体顶点数据的管理者VertexDataManager,具体开发步骤如下. (1)首先为读者介绍的是本类主要框架的开发,其代码如下. 1 pac

如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait.notify 和 notifyAll 来实现线程间的通信..举个例子,如果你的Java程序中有两个线程--即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空).相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再

详解JAVA高质量代码之数组与集合_java

1.性能考虑,优先选择数组 数组在项目开发当中使用的频率是越来越少,特别是在业务为主的开发当中,首先数组没有List,Set等集合提供的诸多方法,查找增加算法都要自己编写,极其繁琐麻烦,但由于List,Set等集合使用泛型支持后,存放的都为包装类,而数组是可以使用基本数据类型,而使用基本数据类型的执行运算速度要比包装类型快得多,而且集合类的底层也是通过数组进行实现. 2.若有必要,使用变长数组 在学习集合类当中,很多人喜欢将数组的定长拿来和集合类型的自变长来做比较,但其实这种比较并不合适,通过观

零基础写Java知乎爬虫之进阶篇_java

说到爬虫,使用Java本身自带的URLConnection可以实现一些基本的抓取页面的功能,但是对于一些比较高级的功能,比如重定向的处理,HTML标记的去除,仅仅使用URLConnection还是不够的. 在这里我们可以使用HttpClient这个第三方jar包. 接下来我们使用HttpClient简单的写一个爬去百度的Demo: import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStr