2022.8.21 读写锁与阻塞队列

9、读写锁

自定义的缓存,没有加锁,就会出现一个没有写入完成,另一个突然插进来的情况

 1  package com.xing.rw;
 2  3  import java.util.HashMap;
 4  import java.util.Map;
 5  6  /**
 7   * ReadWriteLock   写只能有一个,读取可以有多个
 8   */
 9  public class ReadWriteLock {
10      public static void main(String[] args) {
11          MyCache myCache = new MyCache();
12 13 14          //写入
15          for (int i = 1; i<= 5; i++){
16              // 中间变量
17              final int temp = i;
18              new Thread(() -> {
19                  myCache.put(temp+"",temp+"");
20 21              },String.valueOf(i)).start();
22          }
23 24          //读取
25          for (int i = 1; i<= 5; i++){
26              final int temp = i;
27              new Thread(() -> {
28                  myCache.get(temp+"");
29 30              },String.valueOf(i)).start();
31          }
32      }
33  }
34  /**
35   * 自定义缓存
36   */
37  class MyCache{
38          private volatile Map<String,Object> map = new HashMap<>();
39          //
40          public void put(String key,Object Value){
41              System.out.println(Thread.currentThread().getName() + "写入" + key);
42              map.put(key,Value);
43              System.out.println(Thread.currentThread().getName() + "写入OK");
44          };
45          //
46          public void get(String key){
47              System.out.println(Thread.currentThread().getName() + "读取" + key);
48              Object o  = map.get(key);
49              System.out.println(Thread.currentThread().getName() + "读取OK");
50          };
51  }

 

 

使用读写锁

 1  package com.xing.rw;
 2  3  import java.util.HashMap;
 4  import java.util.Map;
 5  import java.util.concurrent.locks.ReentrantReadWriteLock;
 6  7  /**
 8   * 独占锁(写锁) 一次只能被一个线程占用
 9   * 共享锁(读锁) 多个线程可以同时占有
10   * ReadWriteLock
11   * 读- 读 可以共存
12   * 读- 写 不能共存
13   * 写- 写 不能共存
14   *
15   */
16  public class ReadWriteLock {
17      public static void main(String[] args) {
18          MyCacheLock myCacheLock = new MyCacheLock();
19          //写入
20          for (int i = 1; i <= 5; i++) {
21              final int temp = i;
22              new Thread(() -> {
23                  myCacheLock.put(temp + "", temp + "");
24 25              }, String.valueOf(i)).start();
26          }
27          //读取
28          for (int i = 1; i<= 5; i++){
29              final int temp = i;
30              new Thread(() -> {
31                  myCacheLock.get(temp+"");
32 33              },String.valueOf(i)).start();
34          }
35      }
36  }
37  /**
38   * 自定义缓存
39   */
40  //加锁的缓存
41  class MyCacheLock{
42 43      private volatile Map<String,Object> map = new HashMap<>();
44      private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();//读写锁
45 46 47      //写入的时候,只希望同时只有一个线程往里面写
48      public void put(String key,Object Value){
49          // 定义写锁readWriteLock.writeLock()  再加锁
50          readWriteLock.writeLock().lock();//写锁
51          try{
52              System.out.println(Thread.currentThread().getName() + "写入" + key);
53              map.put(key,Value);
54              System.out.println(Thread.currentThread().getName() + "写入OK");
55          }catch (Exception e){
56              e.printStackTrace();
57          }finally {
58              readWriteLock.writeLock().unlock();//解锁
59          }
60 61      };
62 63      //读 所有人都可以读
64      public void get(String key){
65          // 读锁readWriteLock.readLock()
66          readWriteLock.readLock().lock();
67          try{
68              System.out.println(Thread.currentThread().getName() + "读取" + key);
69              Object o  = map.get(key);
70              System.out.println(Thread.currentThread().getName() + "读取OK");
71          }catch (Exception e){
72              e.printStackTrace();
73          }finally {
74              readWriteLock.readLock().unlock();
75          }
76 77      };
78  }
79

 

 

 

 

10、阻塞队列

阻塞队列:

 

 

 

BlockingQueue 是不一个新东西 类似于ArrayList

 

 

 

什么情况下我们会使用阻塞队列:多线程并发,线程池使用的较多

四组API

  • 抛出异常

  • 不抛出异常

  • 阻塞等待

  • 超时等待

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

抛出异常

 1  package com.xing.bq;
 2  3  import java.util.concurrent.ArrayBlockingQueue;
 4  /**
 5   * 抛出异常
 6   */
 7  public class Test1 {
 8      public static void main(String[] args) {
 9          test1();
10      }
11 12      public static void test1(){
13          //参数:队列的大小
14          ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
15 16          // 添加元素  返回Boolean值   true:添加成功
17          System.out.println(arrayBlockingQueue.add("A"));
18          System.out.println(arrayBlockingQueue.add("B"));
19          System.out.println(arrayBlockingQueue.add("C"));
20 21          //队列满了,抛出异常IllegalStateException
22          //System.out.println(arrayBlockingQueue.add("D"));
23 24 25          System.out.println("---------------");
26          System.out.println(arrayBlockingQueue.element());//查看队首的元素
27 28          //谁先进谁先出
29          System.out.println("---------------");
30          System.out.println(arrayBlockingQueue.remove());
31          System.out.println(arrayBlockingQueue.remove());
32          System.out.println(arrayBlockingQueue.remove());
33 34          //队列空,抛出异常NoSuchElementException
35          //System.out.println(arrayBlockingQueue.remove());
36      }
37  }

 

不抛出异常

 1  package com.xing.bq;
 2  3  import java.util.concurrent.ArrayBlockingQueue;
 4  /**
 5   * 不抛出异常,有返回值
 6   */
 7  public class Test2 {
 8      public static void main(String[] args) {
 9          test2();
10      }
11 12      public static void test2(){
13          ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
14 15 16          System.out.println(arrayBlockingQueue.offer("A"));
17          System.out.println(arrayBlockingQueue.offer("B"));
18          System.out.println(arrayBlockingQueue.offer("C"));//true
19          System.out.println(arrayBlockingQueue.offer("D"));//false 不抛出异常 返回一个boolean值
20 21 22          System.out.println("-----------------");
23          System.out.println(arrayBlockingQueue.peek());
24 25 26          System.out.println("-----------------");
27          System.out.println(arrayBlockingQueue.poll());
28          System.out.println(arrayBlockingQueue.poll());
29          System.out.println(arrayBlockingQueue.poll());//依旧是先进先出
30          System.out.println(arrayBlockingQueue.poll());//null 也不抛出异常
31      }
32 33  }
34 35

 

阻塞队列

 1  package com.xing.bq;
 2  3  import java.util.concurrent.ArrayBlockingQueue;
 4  5  /**
 6   * 等待,阻塞(一直阻塞)
 7   */
 8  public class Test3 {
 9      public static void main(String[] args) {
10          try {
11              test3();
12          } catch (InterruptedException e) {
13              e.printStackTrace();
14          }
15      }
16      
17      public static  void test3() throws InterruptedException {
18          ArrayBlockingQueue arrayBlockingQueue =new ArrayBlockingQueue(3);
19          
20          //一直阻塞
21          arrayBlockingQueue.put("A");
22          arrayBlockingQueue.put("B");
23          arrayBlockingQueue.put("C");
24          //arrayBlockingQueue.put("D");//队列没有位置了,他会一直等待
25          
26          System.out.println("----------------");
27          System.out.println(arrayBlockingQueue.take());
28          System.out.println(arrayBlockingQueue.take());
29          System.out.println(arrayBlockingQueue.take());
30          //System.out.println(arrayBlockingQueue.take());  //为空 会一直等待
31      }
32    
33  }
34

 

超时等待

 1  package com.xing.bq;
 2  3  import java.util.concurrent.ArrayBlockingQueue;
 4  import java.util.concurrent.TimeUnit;
 5  /**
 6   * 等待,(超时)
 7   */
 8  public class Test4 {
 9      public static void main(String[] args) {
10          try {
11              test4();
12          } catch (InterruptedException e) {
13              e.printStackTrace();
14          }
15      }
16      public static void test4() throws InterruptedException {
17          ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
18 19          arrayBlockingQueue.offer("a");
20          arrayBlockingQueue.offer("b");
21          arrayBlockingQueue.offer("c");
22          arrayBlockingQueue.offer("d", 2,TimeUnit.SECONDS);//等待超过两秒后执行后面的程序
23 24          System.out.println(arrayBlockingQueue.poll());
25          System.out.println(arrayBlockingQueue.poll());
26          System.out.println(arrayBlockingQueue.poll());
27          // arrayBlockingQueue.poll(2,TimeUnit.SECONDS);
28 29      }
30 31  }
 

同步队列

SynchronousQueue

没有容量,进去一个元素,必须等待取出来之后,才能再往里面放一个元素!

 

 1  package com.xing.bq;
 2  3  4  import java.util.concurrent.BlockingQueue;
 5  import java.util.concurrent.SynchronousQueue;
 6  import java.util.concurrent.TimeUnit;
 7  8  /**
 9   * 同步队列
10   * 和其他的BlockingQueue不一样,SynchronousQueue 不存储元素
11   * put了一个元素,必须先take取出来,否则不能取出值
12   */
13  public class SynchronousQueueDemo {
14      public static void main(String[] args) {
15          //同步队列
16          BlockingQueue<String> blockingDeque = new SynchronousQueue<>();
17 18          new Thread(()->{
19              try {
20                  System.out.println(Thread.currentThread().getName() + "PUT 1");
21                  blockingDeque.put("1");//put():向队列中放入字符串1
22                  System.out.println(Thread.currentThread().getName() + "PUT 2");
23                  blockingDeque.put("2");
24                  System.out.println(Thread.currentThread().getName() + "PUT 3");
25                  blockingDeque.put("3");
26              } catch (InterruptedException e) {
27                  e.printStackTrace();
28              }
29          },"T1").start();
30          new Thread(()->{
31              try {
32                  TimeUnit.SECONDS.sleep(3);//睡3秒
33                  System.out.println(Thread.currentThread().getName() + "取出了:" + blockingDeque.take());// take() 取出队列中的元素
34                  TimeUnit.SECONDS.sleep(3);
35                  System.out.println(Thread.currentThread().getName() + "取出了:" + blockingDeque.take());
36                  TimeUnit.SECONDS.sleep(3);
37                  System.out.println(Thread.currentThread().getName() + "取出了:" +blockingDeque.take());
38 39              } catch (InterruptedException e) {
40                  e.printStackTrace();
41              }
42          },"T2").start();
43      }
44  }
45

 

 

这个例子有点问题,会出现

 
posted @ 2022-08-21 21:38  暴躁C语言  阅读(90)  评论(0编辑  收藏  举报