JUC的小复习

---Start

一、java中如何实现多线程?
        
            1. 继承Thread类
                重写run方法
                run方法是线程体, 存放逻辑代码的位置
            2. 实现Runnable 接口
            3. 实现Callable接口------------main中用FutureTask接收call方法返回的值
            4. 线程池(有的公司不用线程池)

二、线程的生命周期如下图

三、

同步锁:synchronized关键字------自动释放锁
JUC提供的Lock更灵活------手动释放锁等

同步代码块和同步方法,

线程之间的通信:wait,notify notifyAll
JUC提供的 Await,signal,signalAll

死锁-------哲学家就餐问题

虚假唤醒-------------解决-----------把wait方法 放到循环中while

守护线程

            所有的用户线程完成任务后 jvm 就自动关闭, 即使有守护线程运行它也结束,
            如果守护线程任务结束,用户线程还有没结束的,jvm虚拟机不退出
            守护线程就是一个贴了标签的普通线程,处理一些无关紧要的任务

JUC提高并发功能----------java.util.concurrent

Lock接口

lock();上锁
        unlock(); 释放锁
        Lock lock = new ReentrantLock(); 非公平锁-------------synchronized也是非公平锁
        Lock lock = new ReentrantLock(true); 公平锁

 Condition condition =  lock.newCondition();
        condition.await(); 让线程进入到等待池
        condition.signal(); 唤醒等待池中的任意线程
        condition.signalAll(); 唤醒等待池中的所有线程,只有一个能抢到lock锁

线程池:
                ExecutorService executorService = Executors.newSingleThreadExecutor();
                        无限制线程                               Executors.newCachedThreadPool();
          创建固定个数的线程,去执行任务         Executors.newFixedThreadPool(2);
                          定时任务                                 Executors.newScheduledThreadPool(10);

                       executorService.submit(); 可以执行Runnable,Callable接口实现的线程体
                       executorService.execute();可以执行Runnable的线程体                        executorService.shutdown(); 关闭线程池                       

Thread中的sleep,join,yield区别?------思考一下,从以下几个方面来想

1、释放cpu资源吗,2、使用它们时,会让线程进入到生命周期的哪个部分?。

三、JUC包下的集合

写时复制技术:      List接口:        CopyOnWriteArrayList    
                            Set接口:         CopyOnWriteArraySet
                            Map接口:        jdk1.7   分段锁机制:   ConcurrentHashMap();        , 有限制
                                                      jdk1.8   数组 + 链表 + 红黑树 ,然后CAS + synchronized

不要搞混CAS和CAP哦

四、 线程八锁  -----------2种锁-----------8种现象

非静态锁--------------class反射的对象,new几个就几把锁,但要考虑static修饰的情况
静态锁--------static修饰的------全局就一把锁

五、JUC包下的三大辅助类

1.CountDownLatch  闭锁------------------替换 join 方法--------“-”减法

        举个例子====集齐7个七龙珠后,才能召唤神龙

2. CyclicBarrier  循环阻塞类--也叫--循环栅栏    适用----一组线程的相互等待场景-----“+”加法

        举个栗子--------某宝、某夕、某东,双十一双十二结束后,计算“数码区”,“汽车用品区”,   “母婴品区”,它们各自的总流水账,以及它们三个总的流水账,那么比如数码区先获得cpu资源,先计算完后,得等待其他两个区计算结果后,才能计算“总”的流水账

3. Semaphore 信号量--------------适用 “限流” 场景

        举个栗子=========6个车,抢3个车位
                Semaphore semaphore = new Semaphore(3);

大家可以思考一下下面这个问题

有A,B,C三个线程,如何保证三个线程同时执行?
                                如何在并发情况下保证三个线程依次 执行?
                                如何保证三个线程有序交错进行?

六、 读写锁: Lock接口下的另一个实现类:     
     Lock:
         ReetrantLock: 公平锁 , 非公平锁, 可重入锁
         ReentrantReadWriteLock().writeLock(); 写锁
         ReentrantReadWriteLock().readLock(); 读锁
         
         
        写锁的优先级永远大于读锁
        写互斥, 读共享的

七、Volitale 关键字:----------相关的名词:  内存,主存  线程


    内存可见性问题:
        Volatile: 保证数据可见性     保证不了原子性
        synchronized : 每次加载同步代码块,同步方法数据时,都会强制刷新数据的所在位置
                         保证数据是最新的(数据可见)
        Volatile + CAS 算法  ==== synchronized

    多个线程对主存中的数据进行读取操作时,有些线程对内存中的数据更新不知道,导致数据脏读
    为了解决这个问题,我们可以使用Volitale 关键字, 或 synchronized ,强制刷新内存,
    让其它线程是被到被更新的数据,这就是内存可见性问题
    
    但是Volitale 关键字能保证内存可见,保证不了原子性


    如何弥补 Volatile 的原子操作,需要借助 CAS 算法:     
    
    
        CAS = Compare And Swap

八、AtomicStampedReference--------原子引用类----------无锁的线程安全操作====Volatile+CAS
**********************************

 底层维护了一个 Volitale关键字修饰的value值,

方法中使用的时Unsafe的 CompareAndSwap方法,

九、BlockingQueue 阻塞队列

首先要了解:     
            Queue
             Deque
    Queue:  提供了6个方法
    
        有异常的,                              返回特殊值的     null
         add();                                     offer
         element()                                  peek
         remove();                                  poll()  
        
    Deque:  提供了2组方法
   
        有异常的,                               返回特殊值的:
        
        add                                            offer();
        addFirst();                                 offerLast();
        addLast();                                  offerFirst();
        
        element();                                peek();
        getFirst();                                peekFirst();
        getLast();                                  peekLast();
        
        remove();                                   poll();
        removeFirst()                             pollFirst();
        removeLast();                               pollLast();
        
        
    还提供了 push , pop 可以当作栈结构来用
    
    juc:
    
        BlockingQueue:     
            1. ArrayBlockingQueue:
                    put();    向队列中添加元素 ,添加不进去,阻塞
                    take();   从队列的头获取元素,获取不到怎么办  阻塞

            2. LinkedBlockingQueue
                  基于链表结构实现的单向的阻塞队列
                    put();    向队列中添加元素 ,添加不进去,阻塞
                    take();   从队列的头获取元素,获取不到怎么办  阻塞
                    
            3. LinkedBlockingDeque
                  基于链表结构实现的一个双端阻塞队列
                    put();    向队列中添加元素 ,添加不进去,阻塞
                    take();   从队列的头获取元素,获取不到怎么办  阻塞

10、Fork/Join 分支合并
         Fork 拆分: 把大事化小
         
         Join 合并: 把小事儿 聚集到一起,整合
         
        把一个大的任务,拆分成若干个小份 ,然后处理,最后在整合
         
        ForkJoinTask: 拆分合并框架 ,任务类
            1. RecursiveAction    : 用于没有返回结果的任务,
            2. RecursiveTask : 用于有返回结果的任务 例如: 1-----100000 的和
            
        我们的任务类,必须继承上面的工具类,并重写compute方法
        
         初始规则我们自定义
         
         然后要调用fork 拆分
         
         拆分后, 在调用 join 合并
         
        测试类需要使用
        
            ForkJoinPool: 拆分合并池

            执行submit方法,提交,提交后get(); 返回

  • 17
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值