多线程10-模拟缓冲区

1.目标

假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put

操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程

2.代码实现

package org.lkl.thead.foo02;

import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BoundedBufferFoo {

  static class BoundedBuffer{
        Lock lock = new ReentrantLock() ;
        Condition notFull = lock.newCondition() ;
        Condition notEmpty = lock.newCondition() ;
        Object[] queue = new Object[10] ;
        int putptr=0,takeptr=0,count=0  ;
        public void put(Object x ){
            lock.lock() ;
            try {
                while(count == queue.length){ // 队列满 等待take取走数据
                    notFull.await() ;
                }
                //放入数据
                queue[putptr] = x ;
                if(++putptr==queue.length) putptr = 0 ; //归0
                ++count ;
                //放入以后  提醒可以take
                notEmpty.signal() ;
            } catch (Exception e) {

            }finally{
                lock.unlock() ;
            }

        }

        public Object take(){
            lock.lock() ;
            try {
                //为空 则等待
                while(count==0){
                    notEmpty.await() ;
                }
                Object x = queue[takeptr] ;
                if(++takeptr==queue.length) takeptr = 0 ;
                --count ;
                notFull.signal() ; //提醒可以再put
                return x ;
            } catch (Exception e) {
            }finally{
                lock.unlock() ;
            }
            return null ;
        }

    }

    public static void main(String[] args) {
        final BoundedBuffer buffer  = new BoundedBuffer() ;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(500) ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    int putstr = new Random().nextInt(10000) ;
                    buffer.put(putstr) ;
                    System.out.println("put " + putstr);
                }
            }
        }).start() ;

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(2000) ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    Object o = buffer.take() ;
                    System.out.println("get " + o);
                }
            }
        }).start() ;

    }

}

注意 :上面的代码来自JDK API 中Condition的示例代码  在实际的开发中没有必要自己去实现这样子的代码 主要是体现这种思想  在ArrayBlockingQueue类中提供了类似的功能

在take 方法中有个地方要注意: lock.unlock 是在return x 之后执行的,调用return x 之后, take方法的返回值确定下来了但是真个方法并没有结束,finally中一定会执行,千万不要认为这个take

方法没有释放锁.

看下面的一个例子:

public static void main(String[] args) {
            System.out.println(test());
    }

    public static int test() {
        int x = 0 ;
        try {
             x = 23 ;
            System.out.println("before return ");
            return x;
        } catch (Exception e) {
        }finally{
            x = 30 ;
            System.out.println("finally");
        }
        return x  ;

    }

执行结果如下:

before return
finally
23

如果把代码给修改一下:

public static void main(String[] args) {
            System.out.println(test());
    }

    public static int test() {
        int x = 0 ;
        try {
             x = 23 ;
            System.out.println("before return ");
            //return x;
        } catch (Exception e) {
        }finally{
            x = 30 ;
            System.out.println("finally");
        }
        return x  ;

    }
    

执行的结果:

before return
finally
30

通过上面的比较很容易理解前面说的take的情况了.

多线程10-模拟缓冲区,布布扣,bubuko.com

时间: 2024-10-01 23:12:55

多线程10-模拟缓冲区的相关文章

多线程之模拟数据库连接

学习持久化之前,肯定会去连接数据库来进行数据的各种操作,如增.删.改.查,所以对此咋们直接写了一个工具类BaseDAO,今天学习了多线程,所以决定写一个多线程模拟工具类连接数据库.好吧,其实老师要求的. 1 import com.sun.org.apache.xpath.internal.SourceTree; 2 import jdk.internal.util.xml.impl.Input; 3 4 import java.sql.*; 5 import java.sql.Connectio

Java多线程(三)模拟龟兔赛跑

用Runnable接口实现多线程 public class ThreadDemo { public static void main(String[] args) throws InterruptedException { Racer racer = new Racer(); new Thread(racer, "乌龟").start(); new Thread(racer, "兔子").start(); } } class Racer implements Run

java 22 - 11 多线程之模拟电影院售票口售票

使用多线程实现的第二种方式: 首先创建自定义类 1 public class SellTicket implements Runnable { 2 // 定义100张票 3 private int ticket = 100; 4 5 public void run() { 6 7 //假设一直在售票 8 while(true){ 9 //现实中买票时,都会有延迟的,所以让线程休息下 10 try { 11 Thread.sleep(100); 12 } catch (InterruptedExc

多线程技术模拟并行计算之二:数组前缀和(Prefix Sum)

一.前缀和(Prefix Sum)定义: 给定一个数组A[1..n],前缀和数组PrefixSum[1..n]定义为:PrefixSum[i] = A[0]+A[1]+...+A[i-1]: 例如:A[5,6,7,8] --> PrefixSum[5,11,18,26] PrefixSum[0] =A[0] ; PrefixSum[1] =A[0] + A[1] ; PrefixSum[2] =A[0] + A[1] + A[2] ; PrefixSum[3] =A[0] + A[1] + A[

[深入浅出Windows 10]模拟实现微信的彩蛋动画

9.7 模拟实现微信的彩蛋动画 大家在玩微信的时候有没有发现节日的时候发一些节日问候语句如“情人节快乐”,这时候会出现很多爱心形状从屏幕上面飘落下来,我们这小节就是要模拟实现这样的一种动画效果.可能微信里面实现的动画效果都是采用固定的小图片来最为动画的对象,但是我们这小节要对该动画效果增加一些改进,也就是要实现的彩蛋动画的针对的图形形状是动态随机生成的,所以看到从屏幕上面飘落的图形都是形状不太一样的.下面来看一下如何实现星星飘落动画. 9.7.1 实现的思路 首先,我们来分析一下星星飘落动画的实

java多线程下模拟抢票

我们设置三个对象分别同时抢20张票,利用多线程实现. 1 public class Web123506 implements Runnable{ 2 private int ticteksNums=20;//票数 3 4 @Override 5 public void run() { 6 while (true){ 7 if(ticteksNums<0){ 8 break; 9 } 10 /* try { 11 //睡眠 12 Thread.sleep(200); 13 } catch (Int

Java多线程10:ThreadLocal的作用及使用

ThreadLocal的作用 从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的.各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象. 至于为什么要使用ThreadLoca

Java Threads 多线程10分钟参考手册

1         同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一.当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通常把这种情况叫做竞争条件(race condition),把并发访问共享数据的代码叫做关键区域(critical section).同步就是使得多个线程顺序进入关键区域从而避免竞争条件的发生. 1.1       Synchronized关键字 Synchronized是Java多线程编程中最常用的关键字

使用vmware workstation 10模拟安装RAC 11g R2

这里只介绍安装环境,具体安装内容直接下载附件查看即可 VM版本: VMWare-workstations 10 OS版本: OracleLinux-R6-U5-Server-x86_64-dvd_6.5.iso RAC版本: p13390677_112040_Linux-x86-64_1of7.zip p13390677_112040_Linux-x86-64_2of7.zip p13390677_112040_Linux-x86-64_3of7.zip MEM: 1G CPU: 2*2 DIS