当前位置:   article > 正文

【学习笔记】JUC并发编程

【学习笔记】JUC并发编程

【学习笔记】JUC并发编程

教学视频地址:B站尚硅谷JUC并发编程教学视频

代码:实例程序

一、JUC简介

在这里插入图片描述
一些基本概念:
串行:一个一个执行
在这里插入图片描述
管程:monitor监视类,就是平时所说的“锁”


二、Lock接口

1、synchronize

略,详细看之前写的 java基础-多线程 代码

2、Lock

略,详细看之前写的 java基础-多线程 代码


三、线程间的通讯

就是生产者消费者问题 中的那个缓冲池 实现了线程之间的通讯

多线程并发线程步骤:
1、创建共享资源
2、创建并发执行的方法:上锁、判断临界条件、实现逻辑、通知其他进程、解锁

  • sinal的使用
    await()、signal()、signalAll():
    Condition在Java 1.5 中出现,用来代替传统的wait()、notify()、notifyAll()方法,相比于wait()、notify()、notifyAll()方法,await()、signal()、signalAll()更加安全和高效。
    wait()、notify()、notifyAll()方法分别对应于Condition中的await()、signal()、signalAll()。
    Condition简单介绍:
    1、Condition是个接口,基本的方法就是await()和signal()方法;
    2、调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用

四、线程间的定制化通信

  • 引入
    在这里插入图片描述
  • 代码
    在这里插入图片描述

五、集合的线程安全

  • 不安全演示
    在这里插入图片描述
  • 解决方法一
    在这里插入图片描述
  • 方法二
    在这里插入图片描述
  • 方法三
    在这里插入图片描述
    写时复制技术:
    同个进程同时写同时读,没有人要写时则正常读,有人要写则复制一份出来写入新内容,然后再和旧内容合并、覆盖,之后在读取合并后的内容

六、多线程锁

  • synchronize的八种情况
    在这里插入图片描述
    详细例子看代码
  • 公平锁和非公平锁
    在这里插入图片描述

优缺点:
在这里插入图片描述

  • 可重入锁
    获得一把锁后可以重复进入用这把锁加锁的所有区域
    在这里插入图片描述
  • 死锁
    基本内容略
    检查是否发生死锁(java bin里的jsp.exe配到环境变量里)
    在这里插入图片描述

七、Callable接口

即是创建线程的其中一种方式,略


八、辅助类

  • 减少计数类countDownLath
    从x减少到0才可以继续执行
    引入
    在这里插入图片描述
    代码:
public class Test {
    public static void main(String[] args) throws InterruptedException {
        //创建技术类
        CountDownLatch countDownLatch = new CountDownLatch(6);

        //六个同学陆续离开教室
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" 离开");
                //离开后,计数器减一
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }

        //班长锁门,并发顺序不对
        System.out.println("错误锁门----");

        //计数器为零之前让其阻塞
        countDownLatch.await();
        System.out.println("正确锁门-----");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 循环栅栏
    从零增加到x才可以执行特定代码

引入:找到七颗龙珠才可以召唤神龙

代码:

public class Test {
    public static void main(String[] args) {

        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("召唤神龙!!!!!");
        });

        for (int i = 1; i < 8; i++) {
            new Thread(()->{
                System.out.println("第"+Thread.currentThread().getName()+"颗龙珠被搜集。。。。");
                //没搜集完成就阻塞
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 信号量

代码:

public class Test {
    public static void main(String[] args) {
        //三个车位六辆车
        Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i < 7; i++) {
            new Thread(()->{
                //申请信号量
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"抢到车位...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //释放信号量
                    semaphore.release();
                    System.out.println("---"+Thread.currentThread().getName()+"离开车位...");
                }
            },String.valueOf(i)).start();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

九、读写锁

悲观锁:完全上锁,不支持并发
在这里插入图片描述
乐观锁:同时操作时加上版本被标记,最后再合并,冲突则回退,支持并发
在这里插入图片描述
表锁:对一张表中的一条数据操作,将整张表上锁
行锁:对一张表中的一条数据操作,只上锁这一条数据,会发生死锁
在这里插入图片描述
读锁:共享锁,会发生死锁
写锁:独占锁(排他锁),会发生死锁
读写锁代码:


//资源类
class MyCache{
    //创建读写锁
    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public volatile HashMap<String, String> hashMap = new HashMap<>();

    public void put(String key,String value) throws InterruptedException {
        try {
            //上锁
            readWriteLock.writeLock().lock();

            System.out.println(Thread.currentThread().getName()+" 正在进行写操作...");
            hashMap.put(key,value);
            //时停
//            TimeUnit.SECONDS.sleep(100);
            System.out.println(Thread.currentThread().getName()+" 写操作已完成...");
        }finally {
            //解锁
            readWriteLock.writeLock().unlock();
        }

    }

    public String  get(String key) throws InterruptedException {
        String s = null;
        try {
            readWriteLock.readLock().lock();

            System.out.println(Thread.currentThread().getName()+" 正在进行读操作...");
            s = hashMap.get(key);
            //时停
//            TimeUnit.SECONDS.sleep(100);
            System.out.println(Thread.currentThread().getName()+" 读操作已完成...");
        }finally {
            readWriteLock.readLock().unlock();
        }
        return s;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

在这里插入图片描述
锁降级:
在这里插入图片描述


十、阻塞队列

  • 基本概念
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 分类
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 核心方法
    在这里插入图片描述
  • 代码
public static void main(String[] args) throws InterruptedException {
        //长度为三的数组阻塞队列
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println("-------------第一组---------------");
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
//        System.out.println(blockingQueue.add("d"));
        System.out.println("检查:"+blockingQueue.element());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
//        System.out.println(blockingQueue.remove());

        System.out.println("-------------第二组---------------");
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("d"));
        System.out.println("检查:"+blockingQueue.peek());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());

        System.out.println("-------------第三组---------------");
        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());

        System.out.println("-------------第四组-----------------");
        System.out.println(blockingQueue.offer("a",2, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("b",2, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("c",2, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("d",2, TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

十一、ThreadPool线程池

  • 基本概念

  • 使用方式
    在这里插入图片描述

  • 七个参数
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 处理流程
    在这里插入图片描述
    在这里插入图片描述
  • 代码
public static void main(String[] args) {
        //一池多线程
//        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        //一池一线程
//        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        //可扩充线程池
//        ExecutorService threadPool = Executors.newCachedThreadPool();
        //自定义线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,
                5,
                2,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(4),
                new ThreadPoolExecutor.AbortPolicy());


        try {
            for (int i = 0; i < 10; i++) {
                //执行十个线程
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName());
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            threadPool.shutdown();
        }


    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

十二、fork/jion分支合并框架

  • 基本概念
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 实例
    在这里插入图片描述

十三、completablefuture异步回调

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/966828
推荐阅读
相关标签
  

闽ICP备14008679号