【JAVA并发编程实战】11、有界缓存的实现

1、有界缓存的基类

package cn.xf.cp.ch14;

/**
 *
 *功能:有界缓存实现基类
 *时间:下午2:20:00
 *文件:BaseBoundedBuffer.java
 *@author Administrator
 *
 * @param <V>
 */
public class BaseBoundedBuffer<V>
{
    private final V[] buf;
    private int tail;
    private int head;
    private int count;

    public BaseBoundedBuffer(int capacity)
    {
        //初始化数组
        this.buf = (V[]) new Object[capacity];
    }

    //放入一个数据,final方法无法被重写
    protected synchronized final void doPut(V v)
    {
        buf[tail] = v;
        if(++tail == buf.length)
        {
            tail = 0;
        }
        //插入一个方法,总量++
        ++count;
    }

    /**
     * 取出一个数据
     * @return
     */
    protected synchronized final V doTake()
    {
        V v = buf[head];
        buf[head] = null;
        if(++head == buf.length)
        {
            head = 0;
        }
        --count;
        return v;
    }

    //通过对count的判断,来确定数组是否是满的
    public synchronized final boolean isFull()
    {
        return count == buf.length;
    }

    public synchronized final boolean isEmpty()
    {
        return count == 0;
    }
}

2、判定前提条件再执行操作

package cn.xf.cp.ch14;

/**
 *
 *功能:对插入和获取元素操作进行先行检查,然后执行操作,校验不通过不予操作
 *时间:下午2:33:41
 *文件:GrumpyBoundedBuffer.java
 *@author Administrator
 *
 * @param <V>
 */
public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V>
{

    public GrumpyBoundedBuffer(int size)
    {
        super(size);
    }

    public synchronized void put(V v) throws Exception
    {
        //如果是满的队列,就无法插入新的元素
        if(this.isFull())
        {
            throw new Exception("队列超出");
        }
        this.doPut(v);
    }

    //同理,队列为空的就无法取出新的元素
    public synchronized V take() throws Exception
    {
        if(this.isEmpty())
        {
            throw new Exception("队列中无元素");
        }

        return this.doTake();
    }

}

3、通过轮询与休眠来实现简单的阻塞

package cn.xf.cp.ch14;

/**
 *
 *功能:通过轮询与休眠来实现简单的阻塞
 *时间:下午2:55:54
 *文件:SleepyBoundedBuffer.java
 *@author Administrator
 *
 * @param <V>
 */
public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V>
{
    //2s
    private static final long SLEEP_GRANULARITY = 2000;

    public SleepyBoundedBuffer(int capacity)
    {
        super(capacity);
    }

    //放入队列的时候
    public void put(V v) throws InterruptedException
    {
        while(true)
        {
            //这里不对循环上锁,不然这个锁就无法释放了,不对休眠上锁,休眠上锁,在休眠的时候别人也无法操作,永远都不可能有元素出去
            synchronized (this)
            {
                //如果队列不是满的,那么就放入元素
                if(!this.isFull())
                {
                    this.doPut(v);
                    return;
                }
            }
            //否则休眠,退出cpu占用
            Thread.sleep(SLEEP_GRANULARITY);
        }
    }

    public V take() throws InterruptedException
    {
        while(true)
        {
            //这里不对循环上锁,不然这个锁就无法释放了,不对休眠上锁,休眠上锁,在休眠的时候别人也无法操作,永远都不可能有新的元素进来
            synchronized(this)
            {
                //如果数组部位空,那么就可以取出数据
                if(!this.isEmpty())
                {
                    return this.doTake();
                }
                //如果队列为空,休眠几秒再试
            }
            Thread.sleep(SLEEP_GRANULARITY);
        }
    }

}

4、条件队列

package cn.xf.cp.ch14;

/**
 *
 *功能:使用条件队列
 *时间:下午3:32:04
 *文件:BoundedBuffer.java
 *@author Administrator
 *
 * @param <V>
 */
public class BoundedBuffer<V> extends BaseBoundedBuffer<V>
{

    public BoundedBuffer(int capacity)
    {
        super(capacity);
    }

    /**
     * 放入数据元素
     * @param v
     * @throws InterruptedException
     */
    public synchronized void put(V v) throws InterruptedException
    {
        while(this.isFull())
        {
            //这里挂起程序,会释放锁
            this.wait();
        }
        //如果队列不为满的,那么程序被唤醒之后从新获取锁
        this.doPut(v);
        //执行结束,唤醒其他队列
        this.notifyAll();
    }

    public synchronized V take() throws InterruptedException
    {
        while(this.isEmpty())
        {
            this.wait();
        }
        V v = this.doTake();
        this.notifyAll();
        return v;
    }

}
时间: 2024-10-17 11:06:27

【JAVA并发编程实战】11、有界缓存的实现的相关文章

[Java并发编程实战]构建一个高效可复用缓存程序(含代码)

[Java并发编程实战]构建一个高效可复用缓存程序(含代码) 原文地址:https://www.cnblogs.com/chengpeng15/p/9915800.html

《Java并发编程实战》要点笔记及java.util.concurrent 的结构介绍

买了<java并发编程实战>这本书,看了好几遍都不是很懂,这个还是要在实战中找取其中的要点的,后面看到一篇文章笔记做的很不错分享给大家!! 原文地址:http://blog.csdn.net/cdl2008sky/article/details/26377433 Subsections  1.线程安全(Thread safety) 2.锁(lock) 3.共享对象 4.对象组合 5.基础构建模块 6.任务执行 7.取消和关闭 8.线程池的使用 9.性能与可伸缩性 10.并发程序的测试 11.显

《Java并发编程实战》读书笔记

Subsections 线程安全(Thread safety) 锁(lock) 共享对象 对象组合 基础构建模块 任务执行 取消和关闭 线程池的使用 性能与可伸缩性 并发程序的测试 显示锁 原子变量和非阻塞同步机制 一.线程安全(Thread safety) 无论何时,只要多于一个线程访问给定的状态变量.而且其中某个线程会写入该变量,此时必须使用同步来协助线程对该变量的访问. 线程安全是指多个线程在访问一个类时,如果不需要额外的同步,这个类的行为仍然是正确的. 线程安全的实例: (1).一个无状

《Java并发编程实战》/童云兰译【PDF】下载

<Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册.书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险.构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高并发应用程序的吞吐量,如何识别可并行执行的任务,如何提高单线程子

java并发编程实战学习(3)--基础构建模块

转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到空间可用:如果队列为空,那么take方法将阻塞直到有元素可用.队列可以是有界的也可以是无界的. 如果生产者生成工作的速率比消费者处理工作的速率款,那么工作项会在队列中累计起来,最终好紧内存.同样,put方法的阻塞特性也极大地简化了生产者的编码.如果使用有界队列,当队列充满时,生产者将阻

《Java并发编程实战》第八章 线程池的使用 读书笔记

一.在任务与执行策略之间的隐性解耦 有些类型的任务需要明确地指定执行策略,包括: . 依赖性任务.依赖关系对执行策略造成约束,需要注意活跃性问题.要求线程池足够大,确保任务都能放入. . 使用线程封闭机制的任务.需要串行执行. . 对响应时间敏感的任务. . 使用ThreadLocal的任务. 1. 线程饥饿死锁 线程池中如果所有正在执行任务的线程都由于等待其他仍处于工作队列中的任务而阻塞,这种现象称为线程饥饿死锁. 2. 运行时间较长的任务 Java提供了限时版本与无限时版本.例如Thread

【Java并发编程实战】—–“J.U.C”:ReentrantReadWriteLock

ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/读"."读/写"."写/写"操作都不能同时发生.然而在实际的场景中我们就会遇到这种情况:有些资源并发的访问中,它大部分时间都是执行读操作,写操作比较少,但是读操作并不影响数据的一致性,如果在进行读操作时采用独占的锁机制,这样势必会大大降低吞吐量.所以如果能够做

【Java并发编程实战】—–“J.U.C”:Semaphore

信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是独占锁.对于独占锁而言,它每次只能有一个线程持有,而共享锁则不同,它允许多个线程并行持有锁,并发访问共享资源. 独占锁它所采用的是一种悲观的加锁策略,  对于写而言为了避免冲突独占是必须的,但是对于读就没有必要了,因为它不会影响数据的一致性.如果某个只读线程获取独占锁,则其他读线程都只能等待了,这种情况下就限

读书笔记-----Java并发编程实战(一)线程安全性

线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet 1 @ThreadSafe 2 public class StatelessFactorizer implements Servlet{ 3 public void service(ServletRequest req,ServletResponse resp){ 4 BigInteger i = extractFromRequest(req); 5 BigInteger[] fact

《java并发编程实战》笔记(一)

最近在看<java并发编程实战>,希望自己有毅力把它读完. 线程本身有很多优势,比如可以发挥多处理器的强大能力.建模更加简单.简化异步事件的处理.使用户界面的相应更加灵敏,但是更多的需要程序猿面对的是安全性问题.看下面例子: public class UnsafeSequence { private int value; /*返回一个唯一的数值*/ public int getNext(){ return value++; } } UnsafeSequence的问题在于,如果执行时机不对,那么