第四阶段-多线程

多线程

(进程和线程的区别)

根本区别: 进程是操作系统资源分配的基本单位,线程是CPU调度和执行的基本单位
环境区别: 在操作系统中有多个进程同时运行,在同一个进程中又有多个线程同时执行.在通过CPU的调度 
		下,在每个时间片中只有一个线程执行
开销区别: 因为每个进程都有独立的代码和数据空间,所以进程之间的切换开销比较大.
		而线程可以看做一个轻量级的进程,在同一类的线程中,他们的代码和数据空间是共享的,所以线
		程之间的切换开销比较小.
内存分配区别: 系统在运行的时候会给每个进程分配不同的内存空间,而对于线程来说,除了CPU外,系统不
			会给线程分配内存,线程之间只能共享资源.
包含关系: 线程是进程的一部分.
		没有线程的进程可以看做是单线程的
		如果一个进程有多个线程,则执行的过程不是一条线,而是多条线程共同完成的.

1.程序和进程

1.程序和进程的概念

程序: 就是硬盘上存储的、静止的代码。

**进程:**程序的一次执行产生进程。进程是动态向前的。

2.多任务操作系统的工作原理

假定 A,B,C 三个程序开始运行,A、B、C 产生进程 Pa、Pb、Pc。Pa、Pb、Pc 排队轮流使用 CPU。
假设 Pa 先抢占到 CPU,Pa 执行,执行过程中 Pa 需要等待数据输入(I/O 操作、请求网络资源),
此时 CPU 空转,为了提高 CPU 利用率,Pa 被切换出去,Pa 保存当前执行状态,Pa 挂起。Pb 抢占 CPU,Pb 开始执行,Pb 如果没有数据输入,Pb 也可能被切换出去(CPU 时间片到了),Pb 挂起;Pc 抢占到 CPU,开始执行,如果 Pc 有数据输入,Pc 保存当前状态并挂起。此时 3 个进程都挂起,CPU 空闲。CPU 挑选一个进程运行,根据 CPU 执行原则,选中 Pb,Pb 继续执行。
CPU 通过时间片实现多任务,这样的操作系统称为多任务操作系统,但同一时刻还是只有一个进程执行。

3.并发和并行

**并发:**在一段时间内多个进程轮流使用同一个CPU,多个进程形成并发。

**并行:**在同一时刻多个进程使用各自的CPU

2.线程

1.线程工作原理

线程的出现时为了解决实时性问题.
线程是进程的细分.
进程被划分为多个可以独立运行的线程,多个线程配合完成一个进程的任务.
总结:
[1] 线程再次提高了CPU的利用率;
[2] 线程共享进程资源,线程包含在进程中;
[3] 线程细分后称为CPU调度的基本单位.进程称为操作系统资源分配的基本单位.

3.实现线程的方式

1.继承Thread类

// 继承Thread类必须重写run方法
public class AThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5;i++){
            System.out.println("AThread:" + i);
        }
    }
}

// 测试类
public class Test01 {
    public static void main(String[] args) {
        
        // 创建一个线程A
        AThread ta = new AThread();

        // 必须通过start开启线程,不能通过run,通过run就不是一个线程了.
        ta.start();

        // 在主线程中执行一段代码
        for (int i = 0; i < 5;i++){
            System.out.println("main AThread:" + i);
        }

        // 可能存在一个gc线程
    }
}

// 因为多个线程轮流使用CPU,先占用先使用,所以执行结果不确定

2.实现Runnable接口

/**
 * MyRun不是线程,但具备在线程中执行的能力
 */
public class MyRun implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5;i++){
            System.out.println("main AThread:" + i);
        }
    }
}

// 测试类:
public class Test01 {
    public static void main(String[] args) {

        // 1> 创建MyRun对象
        MyRun myRun = new MyRun();
        // 2> 创建线程,把myRun 放入线程中执行
        Thread t = new Thread(myRun);
        t.start();

        // main thread
        for (int i = 0; i < 5;i++){
            System.out.println("myRun:" + i);
        }
    }
}

3.两种实现方式的区别

自定义线程的方式有2,分别是继承Thread方式和实现Runnable接口方式
他们的区别:
[1]继承Thread类后,不能继承其他类,而实现Runnable接口还可以继承其他的类;
[2]实现Runnable接口更方便共享资源.同一份资源,多个线程并发访问.
    
如果多个线程要访问共享资源,优先考虑Runnable方式;如果线程不访问共享资源,可以考虑用继承Thread.
多线程访问共享资源的同时,存在一个严重的问题,导致访问共享资源数据错误问题。

4.多线程的执行轨迹

窗口A卖出一张票,还剩3张
窗口C卖出一张票,还剩2张
窗口B卖出一张票,还剩3张
窗口C卖出一张票,还剩0张
窗口A卖出一张票,还剩1// 假设窗口B抢占到CPU,执行
    for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;///
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");
		}
	}
// i = 0;i < 5;count > 0条件成立,count-- => count=4;
cpu时间片到,B挂起
    
// A抢占到CPU
    for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");///
		}
	}
// i =0;i < 5;count > 0条件成立,count-- => count =3,输出
窗口 A 买出一张票,还剩 3 张
cpu时间片到,A挂起
    
  // 窗口 B 抢占到 CPU,B 从挂起位置开始执行
    for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(//...getName() + "买出一张票,还剩" + count + "张");
		}
	}
// 准备语句:窗口B卖出一张票,还剩3张,还没来得及输出;
                cpu时间片到,B挂起.

  // C抢占到CPU
    for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");///
		}
	}
// i =0;i < 5;count > 0条件成立,count-- => count =2,输出
窗口 C 买出一张票,还剩 3 张
cpu时间片到,C挂起
                
 // 窗口 B 抢占到 CPU,B 从挂起位置开始执行
    for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");///
		}
	}
// 执行准备好的输出语句"窗口B卖出一张票,还剩3张",继续执行,执行到if(count > 0)挂起
                
  // A 抢占到 CPU,A 从挂起的位置开始执行,
	for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");
		}
	}
//执行到准备语句 “窗口 A 卖出一张票,还剩 1 张”,还没输出,
                CPU 时间片到,A 挂起。
                
  // C 抢占 CPU,从挂起位置开始执行
	for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");
		}
	}
输出 “窗口 C 买出一张票,还剩 0 张”
                
	// A 抢占到 CPU,A 从挂起的位置开始执行,
	for (int i = 0; i < 5; i++) {
		if (count > 0) {
			count--;
			System.out.println(...getName() + "买出一张票,还剩" + count + "张");
		}
	}
执行输出语句 “窗口 A 卖出一张票,还剩 1 张”...

总结:

  • 线程通过抢占CPU的方式工作,随时肯CPU时间片到从而被挂起。

  • 由于随时被挂起或者被切除CPU,导致访问共享资源数据错乱。

5.线程的生命周期

新生状态:用new关键字建立一个线程后,该对象就会处于新生状态
		该线程有资源,通过调用start()方法进入就绪状态
    
就绪状态:有资源,无资格:也就是该状态下的线程具备了运行的条件,但是还没分配到CPU.通过CPU		调度进入运行状态.
    
运行状态:有资源,有资源:该状态下的线程具备了运行的条件,也分配到了CPU,执行自己的run方法		中的代码,直到完成任务而死亡或者是因为等待某资源而造成阻塞.如果在给定的时间片		   内没有执行结束,就会被系统给换下来回到就绪状态.
    
阻塞状态:无资源,让资格:该状态下的线程不具备运行的条件,则让出CPU的资格.
    	造成阻塞状态的原因有:
		[1] 等待I/O资源
         [2] 等待网络资源
         [3] 线程A join导致其他线程阻塞
         [4] 线程A sleep导致线程A阻塞
         当阻塞原因消除时该线程就会进入就绪状态.
         
死亡状态:[1]当一个正常运行的线程完成了它的全部工作;
  	 	[2]线程被强制性的终止,如通过stop()方法终止一个线程
     	[3]线程抛出未捕获的异常.

在这里插入图片描述

6.线程的常用方法

1.线程优先级

public class PriorityThread extends Thread{
    public PriorityThread() {
    }

    public PriorityThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(super.getName());
    }
}
public class Test01Priority {
    // 优先级越高,被CPU调动的可能越高,但不一定是优先级越高就一定执行
    // 系统默认的三种优先级
    System.out.println(Thread.MAX_PRIORITY);// 最高
	System.out.println(Thread.MIN_PRIORITY);// 最低
	System.out.println(Thread.NORM_PRIORITY);// 默认
    
    public static void main(String[] args) {
        PriorityThread ta = new PriorityThread("Ta");
        ta.setPriority(Thread.MAX_PRIORITY);
        PriorityThread tb = new PriorityThread("Tb");
        ta.setPriority(Thread.MIN_PRIORITY);

        ta.start();
        tb.start();
    }
}

2.线程的强制执行 join()

/*
t1.join() t1 强制执行,导致其他线程(mainThread)阻塞。当 t1 执行完成后,其他线程阻塞原因消除,进入就绪态。
*/
public class JoinThread extends Thread{
    public JoinThread() {
    }

    public JoinThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 10;i++){
            System.out.println(super.getName() + i);
        }
    }
}
public class Test02Join {
    public static void main(String[] args) {

        JoinThread ta = new JoinThread("线程A");
        ta.start();

        // main thread
        for (int i = 0; i < 10;i++){
            if (2 == i){
                // ta强制执行
                try {
                    ta.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main thread" + i);
        }
    }
}

3.线程休眠 sleep()

/*
线程调用 sleep(毫秒)方法,当前线程进入阻塞态,阻塞时间到后线程进入就绪态
*/
public class SleepThread extends Thread{
    public SleepThread() {
    }

    public SleepThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("开始执行多线程");

        try {
            // 等待10s
            System.out.println("线程即将开始休眠...10s");
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // e.printStackTrace();
            System.out.println("线程在外界被中断...");
        }
        System.out.println("线程正常结束");
    }
}

public class Test03Sleep {
    public static void main(String[] args) {
        SleepThread ta = new SleepThread();
        ta.start();

        System.out.println("主线程开始休眠");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 试图打断ta线程
        ta.interrupt();
    }
}

总结:

总结:
[1] 线程休眠导致当前线程进入阻塞态,休眠时间结束后,线程进入就绪态,抢占 CPU,抢到后继续运行。
[2] 线程休眠过程中可以被中断 ,所有存在一个检查时异常InterruptedException 异常,外界程序中断该线程时,休眠时间提前结束,进入就绪状态,等待 CPU 调度执行。

4.线程礼让 yield()

public class YieldThread extends Thread{
    public YieldThread() {
    }

    public YieldThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 10;i++){
            System.out.println(super.getName() + i);
        }
    }
}

5.线程结束 interrupt(), stop()(不建议)

/*
stop 表示强制停止一个线程。停止一个线程的风险较大,现在不建议使用,通过 interrupt 发中断信号	 中断线程,线程会在何时的时间点结束
interrupt 中止正在运行的线程,该线程不会立即结束,而是继续执行。在适当的时机选择结合异常处理  	机制,异常处理机制可以保证线程继续执行。通过异常处理让一个线程正常结束。interrupt 方法可以	 引导线程正常结束
*/
public class Test03Sleep {
    public static void main(String[] args) {
        SleepThread ta = new SleepThread();
        ta.start();

        System.out.println("主线程开始休眠");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 试图打断ta线程
        ta.interrupt();
    }
}

7.线程同步

**原子性操作:**如果希望一系列操作,要么都执行,要么都不执行。 原子性操作可以认为是业务上不可分割的单元。

1.同步代码块

把原子性操作放到同一个代码块中,就是同步代码块,使用关键字synchronized

语法:
synchronized(mutex){
    // 原子性操作
}
// mutex称为同步锁,也叫互斥锁
public class MyRun implements Runnable{

    private int count = 100;

    @Override
    public void run() {
        // 模拟每个窗口有10个人买票
        for (int i = 0;i < 200;i++){
            synchronized (this){
                if (count > 0){
                    count--;
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"已经卖出一张,还剩"+count+"张");
                }
            }
        }
    }
}
总结:
[1] 如果要实现原子性操作,必须对共享资源加锁(毕加索)
[2] 如果线程运行时申请不是该线程加锁的资源,就会导致该线程阻塞,进入阻塞状态

同步监视器

synchronized(obj){}中的 obj 称为同步监视器

同步代码块中同步监视器可以是任何对象,但是推荐使用共享资源作为同步监视器,且同步监视器不能是基本数据类型。

2.同步方法

当原子性操作的代码很长且可以被重复调用时,可以考虑使用同步方法

语法:
[修饰符] synchronized 返回值类型 方法名称(){
	// 原子性操作
}
// 同步方法中无需指定同步监视器,因为同步方法的监视器是 this,也就是该对象本身
public class MyRun implements Runnable{

    private int count = 100;

    @Override
    public void run() {
        // 模拟每个窗口有10个人买票
        for (int i = 0;i < 200;i++){
            this.saleTicket();
        }
    }
    public synchronized void saleTicket(){
        if (count > 0){
            count--;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"已经卖出一张,还剩"+count+"张");
        }
    }
}

un implements Runnable{

private int count = 100;

@Override
public void run() {
    // 模拟每个窗口有10个人买票
    for (int i = 0;i < 200;i++){
        this.saleTicket();
    }
}
public synchronized void saleTicket(){
    if (count > 0){
        count--;
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"已经卖出一张,还剩"+count+"张");
    }
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
├─第一阶段 │      源码+ppt.rar │      高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │      高并发编程第一阶段02讲、简单介绍什么是线程.wmv │      高并发编程第一阶段03讲、创建并启动线程.mp4 │      高并发编程第一阶段04讲、线程生命周期以及start方法源码剖析.mp4 │      高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │      高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │      高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │      高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │      高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机栈实验.mp4 │      高并发编程第一阶段10讲、Thread构造函数StackSize详细讲解.mp4 │      高并发编程第一阶段11讲、Thread构造函数StackSize详细讲解-续.mp4 │      高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4 │      高并发编程第一阶段13讲、线程ID,优先级讲解.mp4 │      高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4 │      高并发编程第一阶段15讲、Thread中断Interrupt方法详细讲解.mp4 │      高并发编程第一阶段16讲、采用优雅的方式结束线程生命周期.mp4 │      高并发编程第一阶段17讲、Thread API综合实战,编写ThreadService实现暴力结束线程的综合实战.mp4 │      高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4 │      高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4 │      高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │      高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │      高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │      高并发编程第一阶段23讲、多线程死锁分析,案例介绍.mp4 │      高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │      高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │      高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4 │      高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │      高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │      高并发编程第一阶段29讲、如何实现一个自己的显式锁Lock精讲上.mp4 │      高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能).mp4 │      高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │      高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │      高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │      高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │      高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │      高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │      高并发编程第一阶段37讲、给线程池增加拒绝策略以及停止方法.mp4 │      高并发编程第一阶段38讲、给线程池增加自动扩充线程数量,以及闲时自动回收的功能.mp4 │      高并发编程第一阶段39讲、课程结束,内容回顾,下季内容预告.mp4 │ ├─第二阶段 │       Java并发编程.png │       ppt+源码.rar │       高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │       高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │       高并发编程第二阶段03讲、介绍三种高效优雅的Singleton实现方式.wmv │       高并发编程第二阶段04讲、多线程的休息室WaitSet详细介绍与知识点总结.mp4 │       高并发编程第二阶段05讲、一个解释volatile关键字作用最好的例子.mp4 │       高并发编程第二阶段06讲、Java内存模型以及CPU缓存不一致问题的引入.mp4 │       高并发编程第二阶段07讲、CPU以及CPU缓存的结构,解决高速缓存一致性问题的两种方案介绍.mp4 │       高并发编程第二阶段08讲、并发编程的三个重要概念,原子性,可见性,有序性.mp4 │       高并发编程第二阶段09讲、指令重排序,happens-before规则精讲.mp4 │       高并发编程第二阶段10讲、volatile关键字深入详解.mp4 │       高并发编程第二阶段11讲、volatile关键字总结.mp4 │       高并发编程第二阶段12讲、观察者设计模式介绍.mp4 │       高并发编程第二阶段13讲、使用观察者设计模式观察线程的生命周期.mp4 │       高并发编程第二阶段14讲、单线程执行设计模式,有一个门,始终只能一个人通过-上.mp4 │       高并发编程第二阶段15讲、单线程执行设计模式,有一个门,始终只能一个人通过-下.mp4 │       高并发编程第二阶段16讲、多线程读写锁分离设计模式讲解-上.mp4 │       高并发编程第二阶段17讲、多线程读写锁分离设计模式讲解-中.mp4 │       高并发编程第二阶段18讲、多线程读写锁分离设计模式讲解-下.mp4 │       高并发编程第二阶段19讲、多线程不可变对象设计模式Immutable-上.mp4 │       高并发编程第二阶段20讲、多线程不可变对象设计模式Immutable-下.mp4 │       高并发编程第二阶段21讲、多线程Future设计模式详细介绍-上.mp4 │       高并发编程第二阶段22讲、多线程Future设计模式详细介绍-下.mp4 │       高并发编程第二阶段23讲、第二阶段课程答疑学员问题.mp4 │       高并发编程第二阶段24讲、Guarded Suspension设计模式-上.mp4 │       高并发编程第二阶段25讲、Guarded Suspension设计模式-下.mp4 │       高并发编程第二阶段26讲、ThreadLocal使用详解,深入原理介绍.mp4 │       高并发编程第二阶段27讲、多线程运行上下文设计模式介绍.mp4 │       高并发编程第二阶段28讲、使用ThreadLocal重新实现一个上下文设计模式.mp4 │       高并发编程第二阶段29讲、多线程Balking设计模式-上.mp4 │       高并发编程第二阶段30讲、多线程Balking设计模式-下.mp4 │       高并发编程第二阶段31讲、多线程Producer and Consumer设计模式.mp4 │       高并发编程第二阶段32讲、多线程Count Down设计模式.mp4 │       高并发编程第二阶段33讲、多线程Thread-Per-Message设计模式.mp4 │       高并发编程第二阶段34讲、多线程Two Phase Termination设计模式-上.mp4 │       高并发编程第二阶段35讲、多线程Two Phase Termination设计模式-下.mp4 │       高并发编程第二阶段36讲、多线程Worker-Thread设计模式-上.mp4 │       高并发编程第二阶段37讲、多线程Worker-Thread设计模式-上.mp4 │       高并发编程第二阶段38讲、多线程Active Objects设计模式(接受异步消息的主动对象)-上.mp4 │       高并发编程第二阶段39讲、多线程Active Objects设计模式(接受异步消息的主动对象)-中.mp4 │       高并发编程第二阶段40讲、多线程Active Objects设计模式(接受异步消息的主动对象)-下.mp4 │       高并发编程第二阶段41讲、多线程设计模式内容回顾与总结.mp4 │       高并发编程第二阶段42讲、ClassLoader课程大纲介绍.mp4 │       高并发编程第二阶段43讲、类加载的过程以及类主动使用的六种情况详细介绍.mp4 │       高并发编程第二阶段44讲、被动引用和类加载过程的练习巩固训练题.mp4 │       高并发编程第二阶段45讲、ClassLoader加载阶段发生的故事.mp4 │       高并发编程第二阶段46讲、ClassLoader链接阶段(验证,准备,解析)过程详细介绍.mp4 │       高并发编程第二阶段47讲、ClassLoader初始化阶段详细介绍clinit.mp4 │       高并发编程第二阶段48讲、JVM内置三大类加载器的详细介绍.mp4 │       高并发编程第二阶段49讲、自定义类加载器ClassLoader顺便问候了一下世界.mp4 │       高并发编程第二阶段50讲、ClassLoader父委托机制详细介绍.mp4 │       高并发编程第二阶段51讲、加密解密类加载实战演示.mp4 │       高并发编程第二阶段52讲、加密解密类加载实战演示-续.mp4 │       高并发编程第二阶段53讲、ClassLoader打破双父亲委托机制,重写loadClass实战练习.mp4 │       高并发编程第二阶段54讲、ClassLoader命名空间,运行时包,类卸载详细介绍.mp4 │       高并发编程第二阶段55讲、线程上下文类加载器以及数据库驱动案例分析.mp4 │       └─第三阶段        Java并发编程.png        Java高并发第三阶段(JUC).png        高并发编程第三阶段01讲 AtomicInteger多线程下测试讲解.mkv        高并发编程第三阶段02讲 AtomicInteger API详解,以及CAS算法详细介绍.mkv        高并发编程第三阶段03讲 利用CAS构造一个TryLock自定义显式锁.mp4        高并发编程第三阶段04讲 利用CAS构造一个TryLock自定义显式锁-增强并发情况下.mp4        高并发编程第三阶段05讲 AtomicBoolean源码分析.mp4        高并发编程第三阶段06讲 AtomicLong源码分析.mp4        高并发编程第三阶段07讲 AtomicReference详解,CAS算法带来的ABA问题详解.mp4        高并发编程第三阶段08讲 AtomicStampReference详解,解决CAS带来的ABA问题.mp4        高并发编程第三阶段09讲 AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray讲解.mp4        高并发编程第三阶段10讲 AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater讲解.mp4        高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4        高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4        高并发编程第三阶段13讲 一个JNI程序的编写,通过Java去调用C,C++程序.mp4        高并发编程第三阶段14讲 Unsafe中的方法使用,一半是天使,一半是魔鬼的Unsafe.mp4        高并发编程第三阶段15讲 Unsafe背后的汇编指令,牛逼男人背后的女人_.mp4        高并发编程第三阶段16讲 CountDownLatch经典案例讲解-上_.mp4        高并发编程第三阶段17讲 CountDownLatch经典案例讲解及API精讲-中_.mp4        高并发编程第三阶段18讲 CountDownLatch经典案例讲解如何给离散平行任务增加逻辑层次关系-下_.mp4        高并发编程第三阶段19讲 CyclicBarrier工具的使用场景介绍_.mp4        高并发编程第三阶段20讲 CyclicBarrier vs CountDownLatch_.mp4        高并发编程第三阶段21讲 Exchanger工具的使用以及常见问题分析-上_.mp4        高并发编程第三阶段22讲 Exchanger工具的使用以及常见问题分析-下_.mp4        高并发编程第三阶段23讲 Semaphore工具的介绍以及借助于Semaphore构造一个Lock_.mp4        高并发编程第三阶段24讲 Semaphore工具API详细介绍-上_.mp4        高并发编程第三阶段25讲 Semaphore工具API详细介绍-下_.mp4        高并发编程第三阶段26讲 Lock&ReentrantLock详细讲解_.mp4        高并发编程第三阶段27讲 ReadWriteLock&ReentrantReadWriteLock详细讲解_.mp4        高并发编程第三阶段28讲 Condition初步使用,提出几个疑问_.mp4        高并发编程第三阶段29讲 关于Condition疑问的几个小实验,对比Wait&Notify_.mp4        高并发编程第三阶段30讲 使用Condition实现一个多线程下的Producer-Consumer_.mp4        高并发编程第三阶段31讲 JDK8-StampedLock详细介绍-上_.mp4        高并发编程第三阶段32讲 JDK8-StampedLock详细介绍-下.mp4        高并发编程第三阶段33讲 ForkJoin框架之RecursiveTask_.mp4        高并发编程第三阶段34讲 ForkJoin框架之RecursiveAction_.mp4        高并发编程第三阶段35讲 Phaser工具的实战案例使用第一部分_.mp4        高并发编程第三阶段36讲 Phaser工具的实战案例使用第二部分_.mp4        高并发编程第三阶段37讲 Phaser工具的实战案例使用第三部分_.mp4        高并发编程第三阶段38讲 Executor&ExecutorService讲解_.mp4        高并发编程第三阶段39讲 ThreadPoolExecutor七大构造参数详细讲解_.mp4        高并发编程第三阶段40讲 ThreadPoolExecutor关闭(很重要)精讲_.mp4        高并发编程第三阶段41讲 newCache&newFixed&single ExecutorService详解_.mp4        高并发编程第三阶段42讲 newWorkStealingPool ExecutorService详解_.mp4        高并发编程第三阶段43讲 Scheduler的前奏Timer&Linux Crontab & quartz比较_.mp4        高并发编程第三阶段44讲 ExecutorService API详细讲解-上_.mp4        高并发编程第三阶段45讲 ExecutorService 四大内置拒绝策略深入探究_.mp4        高并发编程第三阶段46讲 ExecutorService API详细讲解-中_.mp4        高并发编程第三阶段47讲 ExecutorService API详细讲解-下_.mp4        高并发编程第三阶段48讲 Future&Callable详细讲解-上_.mp4        高并发编程第三阶段49讲 Future&Callable详细讲解-下_.mp4        高并发编程第三阶段50讲 CompletionService详细介绍_.mp4        高并发编程第三阶段51讲 ScheduledExecutorService详细讲解-上_.mp4        高并发编程第三阶段52讲 ScheduledExecutorService详细讲解-下_.mp4        高并发编程第三阶段53讲 知识回顾与串联_.mp4        高并发编程第三阶段54讲 课程问题答疑,ExecutorService中的陷阱_.mp4        高并发编程第三阶段55讲 CompletableFuture的使用精讲(体验)-1_.mp4        高并发编程第三阶段56讲 CompletableFuture的使用精讲(构建)-2_.mp4        高并发编程第三阶段57讲 CompletableFuture的使用精讲(熟练)-3_.mp4        高并发编程第三阶段58讲 CompletableFuture的使用精讲(深入)-4_.mp4        高并发编程第三阶段59讲 CompletableFuture的使用精讲(掌握)-5_.mp4        高并发编程第三阶段60讲 LinkedList和有序LinkedList的实现_.mp4        高并发编程第三阶段61讲 跳表数据结构的Java实现-1_.mp4        高并发编程第三阶段62讲 跳表数据结构的Java实现-2_.mp4        高并发编程第三阶段63讲 跳表数据结构的Java实现(解决Bug)-3_.mp4        高并发编程第三阶段64讲 ArrayBlockingList详细讲解_.mp4        高并发编程第三阶段65讲 PriorityBlockingQueue详细讲解_.mp4        高并发编程第三阶段66讲 LinkedBlockingQueue详细讲解_.mp4        高并发编程第三阶段67讲 SynchronousQueue详细讲解_.mp4        高并发编程第三阶段68讲 DelayQueue详细讲解_.mp4        高并发编程第三阶段69讲 LinkedBlockingDeque详细讲解_.mp4        高并发编程第三阶段70讲 LinkedTransferQueue详细讲解_.mp4        高并发编程第三阶段71讲 七大BlockingQueue的特点总结,可以不用详细看_.mp4        高并发编程第三阶段72讲 ConcurrentHashMap性能测试以及JDK1.7原理讲解_.mp4        高并发编程第三阶段73讲 ConcurrentHashMap性能测试以及JDK1.8原理讲解_.mp4        高并发编程第三阶段74讲 ConcurrentSkipListMap详细讲解_.mp4        高并发编程第三阶段75讲 ConcurrentSkipListMap vs ConcurrentHashMap_.mp4        高并发编程第三阶段76讲 ConcurrentLinkedQueue&ConcurrentLinkedDeque_.mp4        高并发编程第三阶段77讲 CopyOnWriteArrayList&CopyOnWriteArraySet源码分析_.mp4        高并发编程第三阶段78讲 ConcurrentLinkedList vs CopyOnWriteArrayList vs SynchronizedList性能对比_.mp4        高并发编程第三阶段79讲 实现一个高并发的无锁队列(Lock-Free).mp4        高并发编程第三阶段80讲 总结与回顾,闲聊与感谢.mp4
├─第一阶段 │      源码+ppt.rar │      高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │      高并发编程第一阶段02讲、简单介绍什么是线程.wmv │      高并发编程第一阶段03讲、创建并启动线程.mp4 │      高并发编程第一阶段04讲、线程生命周期以及start方法源码剖析.mp4 │      高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │      高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │      高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │      高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │      高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机栈实验.mp4 │      高并发编程第一阶段10讲、Thread构造函数StackSize详细讲解.mp4 │      高并发编程第一阶段11讲、Thread构造函数StackSize详细讲解-续.mp4 │      高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4 │      高并发编程第一阶段13讲、线程ID,优先级讲解.mp4 │      高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4 │      高并发编程第一阶段15讲、Thread中断Interrupt方法详细讲解.mp4 │      高并发编程第一阶段16讲、采用优雅的方式结束线程生命周期.mp4 │      高并发编程第一阶段17讲、Thread API综合实战,编写ThreadService实现暴力结束线程的综合实战.mp4 │      高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4 │      高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4 │      高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │      高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │      高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │      高并发编程第一阶段23讲、多线程死锁分析,案例介绍.mp4 │      高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │      高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │      高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4 │      高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │      高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │      高并发编程第一阶段29讲、如何实现一个自己的显式锁Lock精讲上.mp4 │      高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能).mp4 │      高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │      高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │      高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │      高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │      高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │      高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │      高并发编程第一阶段37讲、给线程池增加拒绝策略以及停止方法.mp4 │      高并发编程第一阶段38讲、给线程池增加自动扩充线程数量,以及闲时自动回收的功能.mp4 │      高并发编程第一阶段39讲、课程结束,内容回顾,下季内容预告.mp4 │ ├─第二阶段 │       Java并发编程.png │       ppt+源码.rar │       高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │       高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │       高并发编程第二阶段03讲、介绍三种高效优雅的Singleto
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值