Java多线程并发编程JUC处理线程的工具包

 * ?线程存在哪些状态??
     * 新建 ➩ start() 就绪 ➩︎ 得到处理器资源 ➩ 运行 ➩ 死亡
     *
     * ?创建线程存在哪几种方式?
     *  1.继承Thread类
     *  2.实现Runnable接口
     *  3.实现Callable接口{
     @link com.run.threads.callable.CallableDemo}
     *  4.线程池 {
     @link com.run.threads.pool.ThreadPoolDemo}
     *
     *  ?实现Runnable接口和Callable接口有什么区别?
     *  • Runnable 接口不会返回结果;
     *  • Callable 接口可以返回结果;
     *  • Callable 需要依赖Future Task实现类的支持,用来接收运算结果;
     *  • Runnable 无法抛出经过检查的异常;
     *  • Runnable 对象和 Callable 对象的相互转换。
     *
     *  ? 线程的start和run有和区别??<线程启动-操作>
     *  ◆ 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行;
     *  ◆ 方法run()称为线程体,它包括了要执行的这个线程的内容,线程就进入运行状态,开始运行run()方法体当中的代码;
     *    --run方法运行结束此线程终止。然后CPU再调度其他线程。「(直接调用run()方法的话,其实根本就没有启动线程的){
     @link com.run.threads.thread.StartRunTest}
     *
     *  ? sleep()wait()方法有何区别??<线程等待-操作>
     *  ◆ 对于sleep()方法,方法是属于Thread类中的。而wait()方法则是属于Object类中的;
     *sleep()方法导致了程序暂停执行指定的时间,让出CPU给其它线程,但是它的监控状态依然保持着,当指定的时间到期了又会自动恢复运行状态;(监控状态就是指定锁的一个概念)
     *  ◆ 在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁进入等待状态,只有针对此对象调用notify()方法后本线程才会重新尝试执行;
     *sleep()方法可以在任何地方使用,wait()方法只能在Synchronized方法或者Synchronized块中使用。
     *{
     @link com.run.threads.thread.WaitAndSleepTest}
     *
     *  ? notify()notifyAll()有什么区别??<线程唤醒-操作>
     *  ◆ Object类中notify()方法,唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会随机选择唤醒其中一个线程。
     *notifyAll()会让处于等待池的所有线程进入锁池去竞争得到锁的机会。
     *
     *  ? 说一下 yeiId()-线程让步操作 <线程让步-操作>
     *  ◆ 当调用Thread.yeiId()方法时,会给线程调度器一个当前线程愿意让出CPU执行时间片的暗示,
     *     --但是线程调度器可能会忽略这个暗示。但是调用yieId()对锁是没有影响的。
     *  ◆ Thread.yieId()会使当前线程让出CPU执行时间片,与其它线程一起重新竞争CPU时间片。
     *   --一般情况下,优先级高的线程有更大的可能性成功竞争得到CPU时间片,但这又不是绝对的,
     *   --有的操作系统对线程优先级并不敏感。{
     @link com.run.threads.thread.YeiIdTest}
     *
     * ? 生产环境下多线程编程是用stop()中断线程的吗??? <线程中断-操作> stop()Interrupt()
     * ◆ 直接调用该线程的stop()方法来结束该线程一该方法通常容易导致死锁,不推荐使用。
     * ✯ 一般都是使用 'Interrupt()方法来中断线程的'*    ▵ 调用 Interrupt(),只是通知了线程应该中断了,这个线程本身并不会因此而改变状态。
     *    ▵ 如果这个线程调用sleep()而使线程处于TIMED-WATlNG阻塞的状态,那么调用Interrupt()线程将立即退出被TIMED-WATlNG阻塞的状态,并抛出InterruptedException异常。
     *    ▵ 许多声明抛出InterruptedException 的方法(如 Thread.sleep(long mills 方法)),抛出异常前,都会清除中断标识位,所以抛出异常后,调用isInterrupted()方法将会返回false.
     *    ▵ 想要使用interrupt()方法终止一个线程需要被调用的线程配合中断。{
     @link com.run.threads.thread.InterruptTest}
     *
     * ? 主线程中,获取子线程的返回值有那些方式??
     *   ◆ Callable 接口方式
     *   ◆ 循环等待方式、或 join方式 {
     @link com.run.threads.thread.GetSubThreadTest}
     *
     *
     * ?? 多线程需要保证的三大核心??
     *   ▸ 原子性
     *   ▸ 顺序性
     *   ▸ 可见性
     *
     * ?? 如何保证?
     *   ▸ Synchronized 关键字
     *   ▸ CAS (原子性)
     *   ▸ Volatile 关键字 (可见性、顺序性)
     *
     * ?? 什么是CAS,CAS会存在哪些问题?(原子性)
     *CAS(Compare-And-Swap) 是一种硬件对并发的支持
     *      --针对处理器操作而设计的处理器总的一种特殊指令[比如:i++]
     *      --用于管理对共享数据的并发访问.
     *
     *    ◆ CAS 是一种无锁的非阻塞算法的实现.
     *      --CAS 包含了3种操作数:需要读写的内存值V、进行比较的值A、拟写入的新值B、
     *      --当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作.{
     @link com.run.threads.multi.CASCase}
     *
     *    ◆ 当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。
     *     --失败的线程不会被挂起,仅是被告知失败,并且允许再次尝试,
     *     --当然也允许失败的线程放弃操作(由开发者自己决定).
     *     -基于这样的原理,CAS操作即使没有锁,也可以发现其它线程对当前线程的干扰,并进行恰当的处理.
     *
     *    ▸ CAS 会存在 ABA 问题.
     *
     * ?? 为什么存在多线程的可见行的问题?
     *1、内存可见行(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,
     *      --需要确保当一个线程修改了对象状态后,其它线程能够看到发生的状态变化。
     *2、之所以存在可见行问题是由于Java内存模型(Java Memory Model)JMM决定的。
     *3、Volatile 关键字可以解决可见行问题。{
     @link com.run.threads.multi.VolatileCase}
     *
     * ?? 为什么存在多线程的顺序性的问题?
     *  ‣ 原因,指令重排是计算机底层堆执行指令的一种优化策略,
     *  ‣ Volatile 关键字可以执行指令重排,synchronized 关键字更轻量级的同步锁,
     *  --利用了内存屏障(Memory barrier)保证特定操作的执行顺序,
     *  -通过插入内存屏障指令,禁止在内存屏障前后的指令执行重排序优化。
     *
     *  ✭ Volatile 关键字
     *   ☛ 可以保证顺序性和可见性,但是保证不了原子性。
     *   ☛ 可以用 Volatile 实现一个双重检查锁的单例模式
     *      Singleton singleton= new Singleton();
     *       1、分配内存空间.
     *       2、初始化对象.
     *       3、将singleton对象指向分配的内存地址.{
     @link com.singleton.patterns.demo.VolatileSingletonDemo}
     *
     *
     * ??说一下如何在高并发环境下保证线程安全的??
     *    ▴ 主要以 对线程安全问题的诱因 以及 多线程的锁机制 的理解来说;
     *      ▵ 线程安全问题的主要 诱因:
     *          -存在共享数据[临界资源]*          -存在多个线程共同操作这些共享数据、
     *      ▵ 解决问题的方法
     *          -同一时刻仅有一个线程在操作共享数据,即加锁.(Synchronized加锁、及Lock同步锁)
     *
     *  ?Synchronized 锁?
     *synchronized 可以把任意一个非Null的对象当作锁.它属于独占式的悲观锁,同时属于可重入锁。
     *synchronized 根据获取的锁分类,可以分为对象锁和类锁。
     *
     *     ❖ Synchronized ,获取对象锁?
     *      ➣ 同步代码块:synchronized(this、类实例对象锁住的是括号中的实例对象)
     *      ➣ 同步非静态(static)方法 synchronized Method,锁是对当前对象的实例对象。
     *
     *     ❖ Synchronized ,获取类锁?
     *      ➣ 同步代码块 synchronized(类名.class),锁住的是小括号中的的类对象(Class对象).
     *      ➣ 同步静态(static)方法 synchronized static method,锁的是当前对象的类对象(Class对象).
     *
     *  ?Synchronized 的底层实现原理,描述一下??
     *synchronized 同步语句块的实现使用的是, MONITORENTER(monitor/监控器 enter/进入)MONITOREXIT(monitor/监控器 exit/退出),两个指令;
     *   ☞ monitor对象存在于,每个Java对象的对象头中;
     *   ☞ 当执行 MONITORENTER(monitor/监控器 enter/进入) 指令时,线程试图获取锁也就是获取 monitor/监控器 的持有权;
     *   ☞ 当 monitor/监控器,计数器为 '0' 则可以成功获取,获取后将锁计数器设置 '1',也就是加 1;
     *   ☞ 相应的在执行 MONITOREXIT(monitor/监控器 exit/退出) 指令后,将锁计数器设为 '0',表明锁被释放.
     *   ☞ 如果获取对象失败,那就当线程就要阻塞等待,直到锁被另外一个线程释放为止.
     *
     *  {
     @link com.run.threads.synch.SynchronizedDemo}
     *
     *   ? Synchronized 修饰方法
     *synchronized 修饰的方法并没有 MONITORENTER(monitor/监控器 enter/进入)MONITOREXIT(monitor/监控器 exit/退出),两个指令;
     *      --取得代之的是 AccSynchronized 标识.
     *    ◆ 通过该 AccSynchronized 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。
     *    ◆ 当方法调用时,调用指令将会检查方法的,ACC_Synchronized 访问标志是否被设置,如果设置了,执行线程将先获取 Monitor, 获取成功之后才能执行方法体
     *     --方法执行完后再释放 Monitor. 在方法执行期间,其它任何线程都无法再获得同一个 Monitor/监控器 对象.
     *    ◆ 两种同步方式本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。
     *     --两个指令的执行是JVM通过调用操作系统的互斥原语 Mutex 来实现。
     *
     *   ?? Synchronized 和 Volatile 关键字的区别??
     *   ► 在某些特定的应用场景下,Synchronized 和 Volatile 可以完成相同的场景,但是二者之间又有很多区别 主要表现在一下几个方面:
     *      ▴ Volatile 本质是在告诉 JVM 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;
     *       -Synchronized 则是锁定当前变量,只有对当前线程可以访问该变量。
     *      ▴ Volatile仅适用在变量级别; Synchronized则可以使用在变量、方法和类级别;
     *      ▴ Volatile标记的变量不会被编辑器优化,Synchronized标记的变量可以被编辑器优化;
     *      ▴ 多线程访问 Volatile 关键字不会发生阻塞,而Synchronized关键字可能会发生阻塞;
     *      ▴ Volatile关键字能保证数据的可见性,但不能保证数据的原子性,Synchronized 关键字都能保证。
     *
     *    JUC   JUC    JUC    JUC    JUC    JUC
     *    ❖ 除了,Synchronized 可以加锁还了解其它的方式同步吗?
     *       ◆ JUC工具包了,{
     @linkplain java.util.concurrent JUC工具包,这是一个处理线程的工具包。}
     *        -这个工具包中有一ReentrantLock类实现类 Lock接口,并提供了与Synchronized相同的互斥性和内存可见性。
     *        -但相较于 Synchronized 提供了更高的处理锁的灵活性.提供了更高的处理锁的灵活性。
     *
     *    ❖ AQS
     *      ◇ ReentrantLock、ReentrantReadWriteLock底层都是基于AQS来实现的;
     *      ◇ AQS:(AbstractQueuedSynchronizer,抽象队列同步器),它是一个并发包的基础组件,用来实现各种锁,各种同步组件的。
     *        --它包含了, state变量、加锁线程、等待队列并发中的核心组件。
     *
     *    ❖ Synchronized 和 ReentrantLock 的比较 ?
     *     ► 两者的共同点:
     *          ⁌ 都是用来协调多线程对共享对象、变量的访问;
     *          ⁌ 都是可重入锁,同一线程可以多次获得同一个锁;
     *          ⁌ 都是保证可见性和互斥性;
     *     ► 不同点:
     *1、ReentrantLock显示的获得、释放锁、synchronized 隐式获得释放锁;
     *2、ReentrantLock 相比 synchronized 的优势是可响应、可轮回、可中断;
     *3、ReentrantLock 是API级别的同步非阻塞锁,乐观锁策略;Synchronized 是JVM级别的同步阻塞锁,悲观锁策略。
     *4、ReentrantLock 可以实现公平锁 Lock lock = new ReentrantLock(boolean f)*5、ReentrantLock 通过Condition,可以绑定多个条件;
     *6synchronized 在发生异常时,会自动释放线程占有的锁;而Lock需要手动释放锁。
     *7、通过Lock可以知道有没有成功获取锁,而Synchronized却无法办到。
     *8、Lock可以提高多个线程进行读写操作的效率,既就是实现读写锁等。
     *       #使用ReentrantLock类,完成三个线程,每个线程的ID,分别是 A、B、C ,完成线程同步交互的问题。
     *       {
     @link com.run.threads.synch.ReentrantLockSynchDemo}
     *
     *  ??线程池,包含哪些内容?
     *  ▸ 线程池管理器: 用于创建并管理线程池;
     *  ▸ 工作线程:线程池中的线程;
     *  ▸ 任务接口:每个任务必须实现的接口,用于工作线程调度其运行;
     *  ▸ 任务队列: 用于存放待处理的任务,提供一种缓存机制;
     *
     *
     * ?? 线程池的创建方式,有哪几种?
     *1newFixedThreadPool(): 创建固定大小的线程池,可以进行自动线程回收;
     *2newCachedThreadPool(): 缓存线程池,线程数量不固定可以根据需求自动的更改数量;
     *3newSingleThreadExecutor():创建单个线程池,线程池中只有一个线程;
     *4newScheduledThreadPool():创建固定大小的线程,可以延迟或定时的执行任务;
     *5WorkStealingPoll(): 内部会创建ForkJoinPool,利用working-stealing算法,并行地处理任务。
     *
     * ??ForkJoinPool类(线程池)的工作原理是什么?
     *     ▹ 就是在将一个大任务,进行拆分(fork)成若干个小任务,再将一个个的小任务运算的结果进行 join 汇总。
     *     ▹ Work-stealing算法:某个线程冲其它队列里窃取任务来执行。
     *
     * ??ForkJoinPool 和 普通的 ThreadPool 有什么区别?
     *    ➣ 相对一般的线程池实现,fork/join框架的优势,体现在对其中包含的任务的处理方式上,
     *    ➣ 一般的线程池,如果一个线程正在执行的任务,由于某些原因无法继续运行,那么该线程会处于等待状态。
     *    ➣ 在fork/join 框架实现中,如果某个字问题由于等待另外一个字问题的完成,而无法继续运行。
     *      -那么处理该子问题的线程,会主动寻找其它,尚未运行的字问题来执行。
     *    ➣ 这种方式减少了线程的等待时间,提高了性能。
     *
     * ??<线程通信>
     *    ?在多线程情况下,如何处理线程间协调通信的?
     *    ◆ 线程的 wait()、notify、join、等API,可以实现线程协调通信的功能。
     *    ◆ JUC {
     @linkplain java.util.concurrent JUC工具包} 中也有很多成熟的线程通信协调工具;
     *      ◇ Condition {
     @linkplain java.util.concurrent.locks.Condition 条件-工具类}
     *      ◇ CountDownLatch {
     @linkplain java.util.concurrent.CountDownLatch 统计向下占有-工具类}
     *      ◇ CyclicBarrier {
     @linkplain java.util.concurrent.CyclicBarrier 环绕屏障-工具类}
     *      ◇ Semaphore {
     @linkplain java.util.concurrent.Semaphore 信号量-工具类}
     *
     *
     *  ??描述一下,线程通信中的,生产者和消费者(Producer-Consumer)问题,有哪些解决方案?
     *   ◆ 生产者-消费者问题,也称有,限缓冲问题(Bounded-buffer).
     *   ◆ 生产者的主要作用是生成一定量的数据放到缓存区中,然后重复此过程.
     *   ◆ 与此同时,消费者也在缓存区消耗这些数据。该问题的关键就是保证生产者不会在缓冲区,满时加入数据,消费者也不会在缓冲区中空时消耗数据。
     *   实现方式列出两种来实现:
     *      ▴ 第一种:Synchronized 和 wait\notifyAll {
     @linkplain com.run.threads.synch.SynchProducerAndConsumerDemo}
     *      ▴ 第二种:ReentrantLock 和 Condition
     *
     *
     * ??描述一个CountDownLatch 类{
     @linkplain java.util.concurrent.CountDownLatch} 的作用和使用场景?
     *   ➢ CountDownLatch 是一个同步辅助类,又称为闭锁.在完成一组正在其它线程中执行的操作之前,
     *     -它运行一个或多个线程一直等待.
     *   以下的应用是可以使用闭锁来实现的:
     *    1、闭锁可以延迟线程的进度,直到其到达终止状态.
     *    2、闭锁可以用来确保,某些活动直到,其他活动都完成才继续执行.
     *    3、确保,某个计算,在其需要的所有资源,都被初始化之后,才继续执行.
     *    4、确保,某个服务,在其服务在其,依赖的所有其他服务,都已经启动之后才启动.
     *    5、等待,直到某个操作所有参与者,都准备就绪,再继续执行。
     *    --典型类似倒计时,功能。{
     @linkplain com.run.threads.synch.SynchCountDownLatchDemo}
     *
     * ??描述一个CyclicBarrier 类{
     @linkplain java.util.concurrent.CyclicBarrier} 的作用和使用场景?
     *CyclicBarrier(循环栏):CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)*     ◇ CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它但功能更加复杂和强大。
     *     ◇ 可以让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所以被屏障拦截的线程才会继续干活。
     *          ▲ 场景:公司组织周末聚餐吃饭,首先员工们(线程),各自从家里到聚餐地点,全部到齐之后,才开始一起吃东西(同步点)*              --假如人员没有到齐(阻塞),到的人只能够等待,直到所有人都到齐之后才可以吃饭。
     *
     * ??描述以下 Semaphore类{
     @linkplain java.util.concurrent.Semaphore}的使用场景?
     *Semaphore(信号量)-允许多个线程同时访问资源:
     *      ◆ ReentrantLock 是一次只允许一个线程访问某个资源、Semaphore 是可以特换它的这个使用场景的。
     *      ◆ Semaphore 通过 acquire() 获取一个许可(加锁),如果没有就等待,而release() 释放一个许可(释放锁)*      ◆ 常用来 限流、需要控制连接数的稀缺资源的业务场景下。
     *          --场景:若一个工厂有5台机器,但是有8个工人,一台机器同时只能被一个工人使用,只有使用完了其它工人才能继续使用。
     *
     *        对比:ReentrantLock 仅允许一个线程访问某个资源,Semaphore 信号量 ,允许多个线程访问某些资源。
     *        {
     @linkplain com.run.threads.synch.SynchSemaphoreDemo}

点击-源代码地址:CodeChina

你可能感兴趣的:(J2EE,多线程,JUC处理线程工具包,Thread,Runnable,Callable)