zoukankan      html  css  js  c++  java
  • 生产者消费者模式的java实现(实现二)

    这次采用ReentrantLock 实现生产者消费者模式,先说下ReentrantLock,通常叫做重入锁,所谓重入就是一个线程可以再次进入已经持有锁的代码块,在内部会对重入的次数进行计数,当计数为0,则释放锁。其实synchronized关键字所代表的内置锁,也是可以重入的。但是又有几点不同:

    1、ReentrantLock将加锁与解锁进行分离,可以提供更细粒度的加解锁操作,内置锁基本都是全局锁(类,对象,代码块)

    2、ReentrantLock提供了定时的加锁操作,这是内置锁无法做到的。

    3、ReentrantLock提供了可轮询的加锁操作,即tryLock()方法,在循环中使用,可以减少线程争抢,减少系统调用和上下文切换,节省资源,这也是内置锁无法做到的。

    package com.smikevon.concurrent;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    
    public class ProducerConsumer_05 {
    
        public static void main(String[] args) {
    
            final Drop drop = new Drop();
    
            new Thread(new Runnable() {
                public void run() {
                    try {
                        new Producer(drop).produce();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"生产者").start();
    
            new Thread(new Runnable() {
                public void run() {
                    try {
                        new Consumer(drop).consume();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"消费者").start();
        }
    
        static class Producer{
            private Drop drop;
            public Producer(Drop drop) {
                this.drop = drop;
            }
    
            public void produce() throws InterruptedException{
                String[] messages = {
                        "我是",
                        "一名程序员",
                        "我很骄傲",
                        "也很自豪",
                        "爱岗敬业",
                        "勤劳奉献",
                        "无怨无悔",
                        "奉献青春",
                        "希望通过学习",
                        "提升",
                        "自己",
                        "done",
                    };
                for(int i=0;i<messages.length;i++){
                    drop.put(messages[i]);
    
                }
    
            }
        }
    
        static class Consumer{
    
            private Drop drop;
            public Consumer(Drop drop) {
                this.drop = drop;
            }
    
            public void consume() throws InterruptedException{
                String message = "";
                do{
                    message = drop.take();
                }while(!message.equals("done"));
            }
        }
    
        static class Drop{
            private Lock lock = new ReentrantLock();
            //初始化条件为空
            private Condition empty = lock.newCondition();
            //条件为满,这里有一个就是满了
            private Condition full = lock.newCondition();
            private String message;
            private boolean isExist = false ;
    
            public void put(String message) throws InterruptedException{
                while(true){
                    try{
                        lock.lock();
                        if(isExist){
                            full.await();
                        }
                        this.message = message;
                        isExist = true;
                        empty.signal();
                        System.out.println(Thread.currentThread().getName()+":"+message);
                        break;
                    }finally{
                        lock.unlock();
                    }
                }
            }
    
            public String take() throws InterruptedException{
                while(true){
                    try{
                        lock.lock();
                        if(!isExist){
                            empty.await();
                        }
                        System.out.println(Thread.currentThread().getName()+":"+message);
                        isExist = false;
                        full.signal();
                        return this.message;
    
                    }finally{
                        lock.unlock();
                    }
                }
            }
        }
    
    }

      这里使用了两个condition,一个表示是否满,一个表示是否空,赋予实际意义,如果有N个线程,定义N个condition条件。这样,在调用signal() 方法时,就是明确告诉该哪个线程从waiting状态中苏醒,恢复runnable状态。减少了内置锁notifyAll()带来的线程争抢锁,争抢时带来的系统调用和上线文切换非常消耗系统资源。

      第一篇和第二篇都是采用原始的锁工具实现生产者消费者模式,实际上java.util.concurrent包提供了一些方便的并发工具,这些工具能够非常方便的实现生产者消费者模式。例如Exchanger,semaphore等。

  • 相关阅读:
    RSA签名算法概述及使用
    PyQt5【入门-窗口】
    CSS的一些文本操作有哪些
    Canvas如何绘制精美的图?
    Python学习路线
    表单都应该提交点什么
    网页的图像、表格以及列表的使用和制作
    网页的头部都装点什么
    HTML5,从零开始
    Redis的安装以及spring整合Redis时出现Could not get a resource from the pool
  • 原文地址:https://www.cnblogs.com/seanvon/p/4071841.html
Copyright © 2011-2022 走看看