Java Lock实现多线程之间的通讯和协作 实践

Lock的await()/signal()/signalAll() 阻塞等待与唤醒

通过Lock和Condition,实现一个生产者消费者的阻塞队列,看看这玩意到底是个啥

直接贴代码,转载自 https://blog.51cto.com/u_15287666/4904942

package com.example.demo.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyBlockedQueue<T> {
    // 使用Lock,生产者和消费者是竞争同一个锁,使用synchronized,生产者和消费者竞争的是同一个锁对象
    final Lock lock = new ReentrantLock();
    // 条件变量:队列不满
    final Condition notFull = lock.newCondition();
    // 条件变量:队列不空
    final Condition notEmpty = lock.newCondition();
    //队列
    private volatile LinkedList<T> list = new LinkedList<>();
    //队列长度
    private final Integer LENGTH = 10;

    // 生产者
    void enq(T x) {
        lock.lock();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            while (list.size() == LENGTH) {
                System.out.println("队列满了....");
                try {
                    // 等待队列不满
                    notFull.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("生产者加入数据:"+x);
            // 省略入队操作
            list.add(x);
            // 入队后, 通知可出队
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    // 消费者
    void deq() {
        lock.lock();
        try {
            while (list.isEmpty()) {
                System.out.println("队列空了....");
                // 等待队列不空
                try {
                    notEmpty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            T v = list.poll();
            System.out.println("消费者消费数据:"+v);
            // 出队后,通知可入队
            notFull.signal();
        } finally {
            lock.unlock();
        }
    }

    public List<T> getList() {
        return list;
    }


    public static void main(String[] args) throws InterruptedException {
        MyBlockedQueue<Integer> myBlockedQueue = new MyBlockedQueue<>();
        //生产者线程
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 20; i++) {
                    myBlockedQueue.enq(i);
                }
            }
        });
        //消费者线程
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    myBlockedQueue.deq();
                }
            }
        });
        thread1.start();
        thread2.start();
        try {
            Thread.sleep(10500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("队列中还剩下没有消费的数据:"+Arrays.toString(myBlockedQueue.getList().toArray()));
    }
}

mian方法,直接运行一下,看控制台输出

D:\JDK\JDK_1.8_201_64\bin\java.exe "-javaagent:D:\IDEA\idea\IntelliJ IDEA 2020.1.1\lib\idea_rt.jar=65134:D:\IDEA\idea\IntelliJ IDEA 2020.1.1\bin" -Dfile.encoding=UTF-8 -classpath D:\JDK\JDK_1.8_201_64\jre\lib\charsets.jar;D:\JDK\JDK_1.8_201_64\jre\lib\deploy.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\access-bridge-64.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\cldrdata.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\dnsns.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\jaccess.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\jfxrt.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\localedata.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\nashorn.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\sunec.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\sunjce_provider.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\sunmscapi.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\sunpkcs11.jar;D:\JDK\JDK_1.8_201_64\jre\lib\ext\zipfs.jar;D:\JDK\JDK_1.8_201_64\jre\lib\javaws.jar;D:\JDK\JDK_1.8_201_64\jre\lib\jce.jar;D:\JDK\JDK_1.8_201_64\jre\lib\jfr.jar;D:\JDK\JDK_1.8_201_64\jre\lib\jfxswt.jar;D:\JDK\JDK_1.8_201_64\jre\lib\jsse.jar;D:\JDK\JDK_1.8_201_64\jre\lib\management-agent.jar;D:\JDK\JDK_1.8_201_64\jre\lib\plugin.jar;D:\JDK\JDK_1.8_201_64\jre\lib\resources.jar;D:\JDK\JDK_1.8_201_64\jre\lib\rt.jar;E:\山大考试\demoTTT\target\classes;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.3.7.RELEASE\spring-boot-starter-web-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter\2.3.7.RELEASE\spring-boot-starter-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot\2.3.7.RELEASE\spring-boot-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.7.RELEASE\spring-boot-autoconfigure-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.3.7.RELEASE\spring-boot-starter-logging-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\windows\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\windows\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;C:\Users\windows\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;C:\Users\windows\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\windows\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\windows\.m2\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.3.7.RELEASE\spring-boot-starter-json-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar;C:\Users\windows\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.7.RELEASE\spring-boot-starter-tomcat-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.37\tomcat-embed-core-9.0.37.jar;C:\Users\windows\.m2\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;C:\Users\windows\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.37\tomcat-embed-websocket-9.0.37.jar;C:\Users\windows\.m2\repository\org\springframework\spring-web\5.2.12.RELEASE\spring-web-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-beans\5.2.12.RELEASE\spring-beans-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-webmvc\5.2.12.RELEASE\spring-webmvc-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-aop\5.2.12.RELEASE\spring-aop-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-context\5.2.12.RELEASE\spring-context-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-expression\5.2.12.RELEASE\spring-expression-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.1\mybatis-spring-boot-starter-2.1.1.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.3.7.RELEASE\spring-boot-starter-jdbc-2.3.7.RELEASE.jar;C:\Users\windows\.m2\repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;C:\Users\windows\.m2\repository\org\springframework\spring-jdbc\5.2.12.RELEASE\spring-jdbc-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.1\mybatis-spring-boot-autoconfigure-2.1.1.jar;C:\Users\windows\.m2\repository\org\mybatis\mybatis\3.5.3\mybatis-3.5.3.jar;C:\Users\windows\.m2\repository\org\mybatis\mybatis-spring\2.0.3\mybatis-spring-2.0.3.jar;C:\Users\windows\.m2\repository\mysql\mysql-connector-java\8.0.11\mysql-connector-java-8.0.11.jar;C:\Users\windows\.m2\repository\org\projectlombok\lombok\1.18.12\lombok-1.18.12.jar;C:\Users\windows\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;C:\Users\windows\.m2\repository\com\alibaba\fastjson\1.2.49\fastjson-1.2.49.jar;C:\Users\windows\.m2\repository\com\squareup\okhttp3\okhttp\3.6.0\okhttp-3.6.0.jar;C:\Users\windows\.m2\repository\com\squareup\okio\okio\1.11.0\okio-1.11.0.jar;C:\Users\windows\.m2\repository\org\springframework\boot\spring-boot-starter-amqp\2.5.5\spring-boot-starter-amqp-2.5.5.jar;C:\Users\windows\.m2\repository\org\springframework\spring-messaging\5.2.12.RELEASE\spring-messaging-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\amqp\spring-rabbit\2.2.9.RELEASE\spring-rabbit-2.2.9.RELEASE.jar;C:\Users\windows\.m2\repository\com\rabbitmq\amqp-client\5.9.0\amqp-client-5.9.0.jar;C:\Users\windows\.m2\repository\org\springframework\amqp\spring-amqp\2.2.9.RELEASE\spring-amqp-2.2.9.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\retry\spring-retry\1.2.5.RELEASE\spring-retry-1.2.5.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-tx\5.2.12.RELEASE\spring-tx-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\windows\.m2\repository\org\springframework\spring-core\5.2.12.RELEASE\spring-core-5.2.12.RELEASE.jar;C:\Users\windows\.m2\repository\org\springframework\spring-jcl\5.2.12.RELEASE\spring-jcl-5.2.12.RELEASE.jar com.example.demo.test.MyBlockedQueue
生产者加入数据:1
生产者加入数据:2
生产者加入数据:3
生产者加入数据:4
生产者加入数据:5
生产者加入数据:6
生产者加入数据:7
生产者加入数据:8
生产者加入数据:9
生产者加入数据:10
队列满了....
消费者消费数据:1
消费者消费数据:2
生产者加入数据:11
生产者加入数据:12
队列满了....
消费者消费数据:3
消费者消费数据:4
消费者消费数据:5
消费者消费数据:6
消费者消费数据:7
消费者消费数据:8
消费者消费数据:9
消费者消费数据:10
生产者加入数据:13
生产者加入数据:14
生产者加入数据:15
生产者加入数据:16
生产者加入数据:17
生产者加入数据:18
生产者加入数据:19
生产者加入数据:20
队列中还剩下没有消费的数据:[11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Process finished with exit code 0

大体说一下
创建2个线程,一个生产者线程,一个消费者线程
生产者线程,如果队列满了,就notFull.await(),阻塞等待,让出锁,如果不满,就加入队列数据,同时唤醒消费者那边的阻塞等待
消费者线程,如果队列为空,咱就notEmpty.await(),阻塞等待,让出锁,如果不为空,就消费

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值