多线程进阶-JUC

54 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天

1.读写锁

ReadWriteLock

image-20221008165629115

独占锁(写锁)一次只能被一个线程占有

共享锁(读锁) 多个线程可以同时占有

读-读 可以共有

读-写 不能共存

写-写 不能共存

 public class ReadWriteLockDemo {
 ​
     public static void main(String[] args) {
         MyCache myCache = new MyCache();
         for (int i = 1; i <=5 ; i++) {
             final  int temp = i ;
             new Thread(()->{
                 myCache.put(temp + "", temp+"");
             },String.valueOf(i)).start();
         }
         for (int i = 1; i <=5 ; i++) {
             final  int temp = i ;
             new Thread(()->{
                 myCache.get(temp + "");
             },String.valueOf(i)).start();
         }
     }
 }
 ​
 ​
 class MyCacheLock{
     private volatile Map<String ,Object> map = new HashMap<>();
     private ReadWriteLock readWriteLock =  new ReentrantReadWriteLock();
 ​
     public void put(String key , Object value){
         readWriteLock.writeLock().lock();
 ​
         try {
             System.out.println(Thread.currentThread().getName()+"写入"+key);
             map.put(key,  value);
             System.out.println(Thread.currentThread().getName()+"写入ok" +key);
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             readWriteLock.writeLock().unlock();
         }
     }
 ​
     public void get(String key){
         readWriteLock.readLock().lock();
         try {
             System.out.println(Thread.currentThread().getName()+"读取"+key);
             Object o = map.get(key);
             System.out.println(Thread.currentThread().getName()+"读取ok" +key);
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             readWriteLock.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()+"写入"+key);
         map.put(key,  value);
         System.out.println(Thread.currentThread().getName()+"写入ok" +key);
     }
 ​
     public void get(String key){
         System.out.println(Thread.currentThread().getName()+"读取"+key);
         Object o = map.get(key);
         System.out.println(Thread.currentThread().getName()+"读取ok" +key);
     }
 }

2.阻塞队列

阻塞

队列

image-20221008193323575

image-20221008194038632

BlockingQueue

blockingQueue 是Collection的一个子类;

什么情况我们会使用 阻塞队列呢?

image-20221008194128050

操作:添加、移除

但是实际我们要学的有:

四组API

方式抛出异常不会抛出异常,有返回值阻塞 等待超时 等待
添加addofferputoffer(timenum,timeUnit)
移除removepolltakepoll(timenum,timeUnit)
判断队列首elementpeek--
   //抛出异常
     public static  void test1(){
         //队列大小
         ArrayBlockingQueue 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());
         //java.util.NoSuchElementException
         //System.out.println(blockingQueue.remove());
     }
 //有返回值,没有异常
     public static  void test2(){
         //队列大小
         ArrayBlockingQueue 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"));
         //java.lang.IllegalStateException: Queue full
         //System.out.println(blockingQueue.add("d"));
         System.out.println(blockingQueue.peek());
 ​
         System.out.println("========================");
 ​
         System.out.println(blockingQueue.poll());
         System.out.println(blockingQueue.poll());
         System.out.println(blockingQueue.poll());
         //java.util.NoSuchElementException
         //System.out.println(blockingQueue.remove());
     }
 ​
  //等待,阻塞(一直)
     public static  void test3() throws InterruptedException {
         //队列大小
         ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
 ​
         blockingQueue.put("a");
         blockingQueue.put("a");
         blockingQueue.put("a");
         //blockingQueue.put("d");
 ​
         System.out.println(blockingQueue.take());
 ​
     }
 ​
  //等待,阻塞(等待超时)
     public static  void test4() throws InterruptedException {
         //队列大小
         ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
         System.out.println(blockingQueue.offer("a"));
         System.out.println(blockingQueue.offer("a"));
         System.out.println(blockingQueue.offer("a"));
         System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS));
 ​
         blockingQueue.poll();
         blockingQueue.poll();
         blockingQueue.poll();
         blockingQueue.poll(2,TimeUnit.SECONDS);
     }

SynchornizeQueue 同步队列

没有容量,

进去一个元素,就必须等待去出来之后,才能在往里放一个元素

put,take

 public class SynchornizeQueue {
     public static void main(String[] args) {
         BlockingQueue<String> blockingQueue =  new SynchronousQueue<>();// 同步队列
 ​
         new Thread(()->{
             try {
                 System.out.println(Thread.currentThread().getName()+"put 1");
                 blockingQueue.put("1");
                 System.out.println(Thread.currentThread().getName()+"put 2");
                 blockingQueue.put("2");
                 System.out.println(Thread.currentThread().getName()+"put 3");
                 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();
 ​
     }
 }