【JUC学习笔记篇】-【基础篇五】

在这里插入图片描述

一、读写锁ReentrantReadWriteLock
概念:
  • 读写锁是指为了解决在多线程的情况下多个线程同时写而且又有多个线程同时去读,造成数据没有写完就有线程来读。而读写锁就是在多个线程可以进行同时读,但是只允许一个线程写,从而保证数据的安全性。
读写锁的降级:
  • 为什么叫降级呢,因为写操作的权限会高于读操作的权限,即由高到低的过程就叫降级。是指读写锁在读的时候不允许写,但是在写的时候是可以允许读的,其过程就是 先获得写锁 --> 再获得读锁 --> 释放写锁 --> 释放读锁
public class ReentrantReadWriteLockDemo {
    public static void main(String[] args) {
        ReentrantReadWriteLock reentrantLock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.WriteLock  writeLock =  reentrantLock.writeLock();
        ReentrantReadWriteLock.ReadLock readLock = reentrantLock.readLock();

        //先获得写锁
        writeLock.lock();
        System.out.println("先获得写锁");

        //再获得读锁
        readLock.lock();
        System.out.println("再获得读锁");

        //释放写锁
        writeLock.unlock();
        //释放读锁
        readLock.unlock();
    }
}

那能不能锁的升级呢?

  		//先获得读锁
        readLock.lock();
        System.out.println("先获得读锁");

        //再获得写锁
        writeLock.lock();
        System.out.println("再获得写锁");

很明显我的程序停在这里了,我在读的过程又有新的线程往里面写这似乎不太合理,我读完了释放锁了然后才可以进行写的操作

在这里插入图片描述


二、阻塞队列BlockingQueue
概念:
  • 队列的特点:先进先出 即先进入队列的先从队列出去。那阻塞队列是指当一个线程从左边往队列中放数据时队列中是满的就会阻塞,当一个线程从队列的右边取数据的时候队列中是空的也会阻塞,这就叫阻塞队列。
分类:
名称简介
ArrayBlockingQueue基于数组、长度固定、最大长度Integer.MAX_VALUE
LinkedBlockingQueue基于链表、长度固定、最大长度Integer.MAX_VALUE
DelayQueue设定延迟时间,达到延迟时间才可以取出,无界阻塞队列,生产者不会阻塞但消费者会
PriorityBlockingQueue采用Comparator比较器排序,无界阻塞队列
SynchronousQueue队列中只允许一个元素,每个插入操作必须等待另一个线程的删除操作
LinkedTransferQueue基于链表的无界队列
LinkedBlockingDeque基于链接节点的可选有界阻塞双端队列。可选的容量绑定构造函数参数用作防止过度扩展的一种方式。容量(如果未指定)等于 Integer.MAX_VALUE。链接节点在每次插入时动态创建,除非这会使双端队列超出容量。
核心方法:
分类抛异常布尔值及null阻塞超时
新增add(e)offer(e)put(e)offer(e,time,unit)
删除remove()poll(),队列为空返回nulltake()poll(time,unit)
检查element()peek()

三、线程池ThreadPool
概念:
  • 用来存放线程的池子,使用完一个线程再放回线程池从而达到循环利用的效果提升效率,但是创建过多的线程反而会带来额外的开支,并不能提升程序的效率可能还会降低效率。
Executors线程工具类创建线程池:
  • newFixedThreadPool 创建指定数量的线程池

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    
  • newSingleThreadExecutor 创建单个线程的线程池

    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    
  • newCachedThreadPool 具有弹性的创建线程的线程池,来的任务多则多创建线程,任务执行完则恢复原来设定的线程数量

    ExecutorService executorService = Executors.newCachedThreadPool();
    
自定义线程池:
  • 通过Executors工具类创建线程池时其底层都是通过new ThreadPoolExecutor()对象来创建的

  • ThreadPoolExecutor的七个参数

    参数名称释义
    int corePoolSize核心线程数
    int maximumPoolSize最大线程数
    long keepAliveTime保持存活的时间
    TimeUnit unit时间单位
    BlockingQueue workQueue阻塞队列
    ThreadFactory threadFactory创建线程的线程工厂
    RejectedExecutionHandler handler队列满了的拒绝策略
线程池的执行流程:

在这里插入图片描述

实际工作中我们并不会采用默认的三种创建线程池的方式,因为他们都快有可能会导致OOM,更多的是自定义线程池。


四、Fork和Join
概念:
  • Fork: 将一个大的任务拆分成多个小的任务
  • Join: 将多个小的任务结果组合成一个结果
使用:

完成0~100的总和:要求两数差值小于等于10

先创建一个任务继承RecursiveTask

class MyTask extends RecursiveTask<Integer> {
    private static final Integer NUMBER = 10;
    private  int begin;
    private  int end;
    private  int result;

    public MyTask(int begin,int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        if ((end-begin) <= NUMBER){
            for (int i = begin; i <= end ; i++) {
                result += i;
            }
        }else {
            int middle = (begin + end) >> 1;

            MyTask beginToMiddle = new MyTask(begin, middle);

            MyTask middleToEnd = new MyTask(middle + 1, end);
            //拆分结果
            beginToMiddle.fork();
            middleToEnd.fork();

            //合并结果
            result = beginToMiddle.join() + middleToEnd.join();
        }
        return result;
    }
}

使用forkJoinPool 完成任务

public class ForkAndJoin {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        MyTask myTask = new MyTask(0,100);

        ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask);
        Integer value = forkJoinTask.get();
        System.out.println(value);
        
        forkJoinPool.shutdown();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值