ReadWriteLock(读写锁)和阻塞队列BlockingQueue与同步队列SynchronousQueue

2023-09-17 16:09:05

1.ReadWriteLock

package com.kuang.rw;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 独占锁(写锁) 一次只能被一个线程占有
 * 共享锁(读锁)  一次能被多个线程占有
 * ReadWriteLock 只对put加锁,读写不互斥,会出现脏读,幻读情况
 * 读-读  可以共存!
 * 读-写   不能共存!
 * 写-写     不能共存!
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCacheLock myCache = new MyCacheLock();

        for (int i = 0; i < 5; i++) {

            int finalI = i;
            new Thread(()->{
                myCache.put(finalI+"",finalI+"");
            },String.valueOf(i)).start();
        }
        for (int i = 0; i < 5; i++) {

            int finalI = i;
            new Thread(()->{
                myCache.get(finalI+"");
            },String.valueOf(i)).start();
        }

    }
}

/**
 * 自定义缓存
 *
 */
//加了锁的
class MyCacheLock{

    private volatile Map<String,Object> map =new HashMap<>();

    private ReadWriteLock lock =new ReentrantReadWriteLock();



    //存,写 只希望同时只有一个线程写
    public void put(String key,Object value){
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"写入开始");
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    //取,读  读写分离,读写互斥,读读不互斥,写写互斥
    public void get(String key){
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"读取开始"+key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName()+"读取完成"+o);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }


}
class MyCache{

    private volatile Map<String,Object> map =new HashMap<>();



    //存,写
    public void put(String key,Object value){
        System.out.println(Thread.currentThread().getName()+"写入开始");
        map.put(key,value);
        System.out.println(Thread.currentThread().getName()+"写入完成");
    }

    //取,读
    public void get(String key){
        System.out.println(Thread.currentThread().getName()+"读取开始"+key);
        map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取完成");
    }


}

 2.阻塞队列BlockingQueue

BlockingQueue 不是新的东西

什么情况下我们会使用阻塞队列: 

多线程并发处理,线程池!

 

方式      抛出异常有返回值,不抛出异常阻塞等待超时等待
添加add()offer()put()
offer("d",2, TimeUnit.SECONDS);
移出remove()poll()take()
poll(2,TimeUnit.SECONDS)
检测队首元素element()peek()

 2.1抛异常的

    /**
     * 抛出异常
     *
     */

    public static void test1(){
        //队列的大小
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        /*
        java.lang.IllegalStateException: Queue full 抛出异常 !
        System.out.println(blockingQueue.add("d"));
         */
        System.out.println("=======================");
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());

    /*
    Exception in thread "main" java.util.NoSuchElementException  抛出异常 !
        System.out.println(blockingQueue.remove());
     */


    }

2.2 有返回值,不抛出异常

  /**
     * 有返回值,不抛出异常!
     */
    public static void test2(){
        //队列的大小
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
      //  System.out.println(blockingQueue.offer("d"));//false 不抛出异常!
        System.out.println("==============");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());//null  不抛出异常
    }

2.3 等待,一直阻塞

   /**
     * 等待,阻塞(一直)
     */
    public static void test3() throws InterruptedException {
        //队列的大小
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
       //一直阻塞
        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");
//        blockingQueue.put("d");//队列没有位置了
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());// 没有这个元素,一直阻塞


    }

2.4 等待阻塞, 超时就解除阻塞


    /**
     * 等待,阻塞(等待超时)
     */
    public static void test4() throws InterruptedException {
        //队列的大小
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        //   blockingQueue.offer("d",2, TimeUnit.SECONDS);//等待超过2秒就退出

        System.out.println("==================");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));//等待超过两秒就不阻塞了,就往下继续执行!
        System.out.println("结束");
    }

3.同步队列SynchronousQueue

package com.kuang.blockQueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * 同步队列
 * 和其他的BlockingQueue 不一样 ,SynchronousQueue不存储元素
 * put了一个元素,必须从里面先take取出来,否则不能在put进去值
 */
public class SynchronousQueueDemo {
    public static void main(String[] args) {
        BlockingQueue<String> blockingQueue = new SynchronousQueue<>();//同步队列

        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"put1");
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName()+"put2");
                blockingQueue.put("2");
                System.out.println(Thread.currentThread().getName()+"put3");
                blockingQueue.put("3");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"T1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"="+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"="+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"="+blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        },"T2").start();


    }
}

更多推荐

7.2 通过API创建新进程

创建新的进程是Windows程序开发的重要部分,它可以用于实现许多功能,例如进程间通信、并行处理等。其中,常用的三种创建进程的方式分别是WinExec()、ShellExecute()和CreateProcessA(),这三种创建进程的方式各有特点。如果需要创建简单进程或从其他程序启动新进程,可以使用WinExec()

qq邮箱smtp要怎样设置开启状态?

qq邮箱smtp是一个重要的发信服务,不仅适用于企业也适用于个人用户。为了提高邮件的触达率和有效性,开启qq邮箱smtp服务是必须的。那么,怎样开启qq邮箱smtp服务?怎么设置?下面蜂邮就给大家介绍一下。一、开启qq邮箱smtp服务qq邮箱smtp是qq的高级邮箱服务之一,需要先开启高级功能才可以使用。开启操作如下:

如何实现一个简单的深度优先搜索(DFS)算法?

聚沙成塔·每天进步一点点⭐专栏简介⭐实现深度优先搜索⭐写在最后⭐专栏简介前端入门之旅:探索Web开发的奇妙世界记得点击上方或者右侧链接订阅本专栏哦几何带你启航前端之旅欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一

Java中的隐式转换和强制转换底层是怎么做的?

目录1.回顾数值型基本数据类型共有哪些?2.什么时候进行隐式类型转换?3.数据类型的隐式转换规则4.特殊隐式转换规则需牢记5.隐式转换小练习5.1byte与byte如何转?5.2int,long,double的转换5.3byte,short,long的转换6.强制转换如何转换?7.强制转换有哪些问题?1.回顾数值型基本

Windows如何删除“$WINDOWS.~BT“文件夹,解决权限不足无法删除

$WINDOWS.~BT是干嘛的$Windows.BT是升级或者安装Windows操作系统中间过程中产生的临时文件夹,一般用于保存下载后的升级文件,或者安装过程中复制文件时产生的。用于保存Windows安装记录,包括配置资料,错误报告等,如果安装失败便可反馈给微软公司,帮助用户解决安装过程中出现的问题。如果系统可正常运

GaussDB数据库SQL系列-表连接(JOIN)

目录一、前言二、GaussDBJOIN1、LEFTJOIN2、LEFTJOINEXCLUDINGINNERJOIN3、RIGHTJOIN4、LEFTJOINEXCLUDINGINNERJOIN5、INNERJOIN6、FULLOUTERJOIN7、FULLOUTERJOINEXCLUDINGINNERJOIN三、Gau

Intel汇编在VS下开发的环境配置

1.创建一个C/C++的空项目2.创建汇编源码文件,就是C++文件改后缀为asm3.在生成依赖项一栏中选择自定义4.选择masm5.在源文件上右击选择属性6.这么设置一下7.为了让代码看的更舒服一些,添加一些高亮插件8.安装AsmHighligher和AsmDude插件(非必须),其中前者主要是高亮配色(个人很喜欢这个

Android存储权限完美适配(Android11及以上适配)

一、Bug简述一个很普通的需求,需要下载图片到本地,我的三个测试机(荣耀Android10,红米11和小米Android13都没有问题)。然后,主角登场了,测试的三星Android13死活拉不起存储权限弹窗。想了下,三星的系统可能和小米的系统做了些区别。于是就是看了下存储权限的版本更迭,却是发现了些骚东西。二、原因很早

Java Script

初识JavaScriptJavaScript是什么?JavaScript(简称JS)是世界上最流行的编程语言之一是一个脚本语言,通过解释器运行主要在客户端(浏览器)上运行,现在也可以基于node.js在服务器端运行JavaScript最初只是为了完成简单的表单验证(验证数据合法性),结果后来不小心就火了.当前JavaS

Android 显示surfaceFlinger vsync 获取

文章目录vsync的概念vsync应用层获取的方式vsync信号传递vsync的概念vsync简单理解就是一帧图像在显示设备这边显示完成之后(图像从左上角扫描到了右下角了)发送的第一个硬件vsync信号,显示设备重新回到左上角开始显示的时候会在发第二个vsync信号。在发送第一个vsync信号出来的时候,上层要开始准备

IP归属地在金融行业的应用场景

IP归属地查询在各大行业当中的利用率可以说非常的高了,提供了各种的保障,比如安全保障、数据保障、性能保障等等。今天我就来详细说一说IP归属地在金融行业的应用场景有哪些?用途一:通过解析用户IP地址所处的区县位置与表单填写位置或者GPS位置进行交叉验证,判断位置是否一致;用途二:识别来自高危地区的IP地址,如缅甸、老挝;

热文推荐