汪文君高并发编程总结-第一阶段

汪文君高并发编程总结-第一阶段

例子1-线程的创建

public class TryConcurrency {

    public static void main(String[] args) {
        Thread t = new Thread("READ-Thread") {
            @Override
            public void run() {
                println(Thread.currentThread().getName());//main
                readFromDataBase();
            }
        };

        t.start();

        new Thread("WRITE-Thread") {
            @Override
            public void run() {
                writeDataToFile();
            }
        }.start();
    }

    private static void readFromDataBase() {
        //read data from database and handle it.
        try {
            println("Begin read data from db.");
            Thread.sleep(1000 * 30L);
            println("Read data done and start handle it.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        println("The data handle finish and successfully.");
    }

    private static void writeDataToFile() {
        try {
            println("Begin write data to file.");
            Thread.sleep(2000 * 20L);
            println("Write data done and start handle it.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        println("The data handle finish and successfully.");
    }

    private static void println(String message) {
        System.out.println(message);
    }
}

例子2-Tread类的模板方法

public class TemplateMethod {

    public final void print(String message) {
        System.out.println("################");
        wrapPrint(message);
        System.out.println("################");
    }

    protected void wrapPrint(String message) {

    }

    public static void main(String[] args) {
        TemplateMethod t1 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("*"+message+"*");
            }
        };
        t1.print("Hello Thread");

        TemplateMethod t2 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("+"+message+"+");
            }
        };

        t2.print("Hello Thread");

    }
}

1.Java应用程序的main函数是一个线程,是被JVM启动的时候调用,线程的名字叫main

2.实现一个线程,必须创建Thread实例,override run方法,并且调用start方法

3.在jvm启动后实际上有多个线程,但是至少有一个非守护线程

4.当你调用一个线程start方法的时候,此时至少有两个线程,一个是调用你的线程,还有一个是启动的线程

5.线程的生命周期分为new,runnable,running,block,terminated

例子3

多线程银行窗口排号的例子

  • 版本V1
public class TicketWindow extends Thread {
    private String name;

    private final static Integer MAX = 50;

    private  Integer i = 1;

    public TicketWindow(String name ) {
        this.name = name;
    }

    @Override
    public void run() {
        while (i <= MAX) {
            System.out.println(name+"号码为:"+i++);
        }
    }
}
public class Back {
    public static void main(String[] args) {
        TicketWindow t1 = new TicketWindow("窗口1");
        t1.start();

        TicketWindow t2 = new TicketWindow("窗口2");
        t2.start();
        TicketWindow t3 = new TicketWindow("窗口3");
        t3.start();
    }
}

V1版本显然满足不了需求

  • 升级版本V2
public class TicketWindowV2 implements Runnable {

    private final static Integer MAX = 50;

    private Integer index = 1;

    @Override
    public void run() {
        while (index <= MAX) {
            System.out.println(Thread.currentThread() + " 的号码为:" + index++);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class BackV2 {
    public static void main(String[] args) {
        final TicketWindowV2 windowV2 = new TicketWindowV2();

        Thread t1 = new Thread(windowV2,"窗口1");
        Thread t2 = new Thread(windowV2,"窗口2");
        Thread t3 = new Thread(windowV2,"窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

V2运行结果:

Thread[窗口1,5,main] 的号码为:1
Thread[窗口3,5,main] 的号码为:2
Thread[窗口2,5,main] 的号码为:1
Thread[窗口3,5,main] 的号码为:3
Thread[窗口1,5,main] 的号码为:4
Thread[窗口2,5,main] 的号码为:5
Thread[窗口1,5,main] 的号码为:6
Thread[窗口3,5,main] 的号码为:7
Thread[窗口2,5,main] 的号码为:8
Thread[窗口2,5,main] 的号码为:9
Thread[窗口3,5,main] 的号码为:11
Thread[窗口1,5,main] 的号码为:10
Thread[窗口2,5,main] 的号码为:12
Thread[窗口3,5,main] 的号码为:12
Thread[窗口1,5,main] 的号码为:13
Thread[窗口1,5,main] 的号码为:14
Thread[窗口2,5,main] 的号码为:16
Thread[窗口3,5,main] 的号码为:15
Thread[窗口1,5,main] 的号码为:17
Thread[窗口2,5,main] 的号码为:19
Thread[窗口3,5,main] 的号码为:18
Thread[窗口1,5,main] 的号码为:20
Thread[窗口2,5,main] 的号码为:21
Thread[窗口3,5,main] 的号码为:22
Thread[窗口2,5,main] 的号码为:23
Thread[窗口3,5,main] 的号码为:25
Thread[窗口1,5,main] 的号码为:24
Thread[窗口1,5,main] 的号码为:26
Thread[窗口3,5,main] 的号码为:27
Thread[窗口2,5,main] 的号码为:28
Thread[窗口1,5,main] 的号码为:29
Thread[窗口3,5,main] 的号码为:30
Thread[窗口2,5,main] 的号码为:30
Thread[窗口3,5,main] 的号码为:31
Thread[窗口1,5,main] 的号码为:32
Thread[窗口2,5,main] 的号码为:31
Thread[窗口3,5,main] 的号码为:32
Thread[窗口2,5,main] 的号码为:33
Thread[窗口1,5,main] 的号码为:33
Thread[窗口1,5,main] 的号码为:34
Thread[窗口2,5,main] 的号码为:35
Thread[窗口3,5,main] 的号码为:34
Thread[窗口2,5,main] 的号码为:36
Thread[窗口1,5,main] 的号码为:37
Thread[窗口3,5,main] 的号码为:37
Thread[窗口1,5,main] 的号码为:38
Thread[窗口2,5,main] 的号码为:39
Thread[窗口3,5,main] 的号码为:40
Thread[窗口1,5,main] 的号码为:41
Thread[窗口2,5,main] 的号码为:41
Thread[窗口3,5,main] 的号码为:42
Thread[窗口1,5,main] 的号码为:43
Thread[窗口2,5,main] 的号码为:44
Thread[窗口3,5,main] 的号码为:45
Thread[窗口2,5,main] 的号码为:46
Thread[窗口1,5,main] 的号码为:46
Thread[窗口3,5,main] 的号码为:47
Thread[窗口1,5,main] 的号码为:48
Thread[窗口2,5,main] 的号码为:48
Thread[窗口3,5,main] 的号码为:49
Thread[窗口1,5,main] 的号码为:50
Thread[窗口2,5,main] 的号码为:51

可以看到叫的号可能会重复,最后拿到的号也大于50了

例子4-用策略模式实现计算器

@FunctionalInterface
public interface CalculatorStrategy {
    double calculator(double salary,double bonus);
}
public class CalculatorStrategyImpl implements CalculatorStrategy {
    private final static double SALARY_RATE = 0.1;
    private final static double BONUS_RATE = 0.15;
    @Override
    public double calculator(double salary, double bonus) {
        return salary*SALARY_RATE+BONUS_RATE*bonus;
    }
}
public class TaxCalculator {
    private final double salary;
    private final double bonus;

    private  CalculatorStrategy calculatorStrategy;

    public TaxCalculator(double salary, double bonus, CalculatorStrategy calculatorStrategy) {
        this.salary = salary;
        this.bonus = bonus;
        this.calculatorStrategy = calculatorStrategy;
    }
    public TaxCalculator(double salary, double bonus) {
        this.salary = salary;
        this.bonus = bonus;
    }
    public double calculate(){
        return this.calcTax();
    }

    protected double calcTax() {
        return calculatorStrategy.calculator(salary,bonus);
    }

    public void setCalculatorStrategy(CalculatorStrategy calculatorStrategy) {
        this.calculatorStrategy = calculatorStrategy;
    }

    public double getSalary() {
        return salary;
    }

    public double getBonus() {
        return bonus;
    }
}
public class TaxCalculatorMain {
    public static void main(String[] args) {

        TaxCalculator taxCalculator = new TaxCalculator(10000d, 2000d);
        CalculatorStrategy strategy = new CalculatorStrategyImpl();
        taxCalculator.setCalculatorStrategy(strategy);
        System.out.println(taxCalculator.calculate());
        //采用Java8
        TaxCalculator taxCalculator2 = new TaxCalculator(10000d, 2000d, (a, b) -> a * 0.1 + b * 0.15);
        System.out.println(taxCalculator2.calculate());
    }
}

例子5

// 线程的创建,线程名称自增规则,命名方式
public class CreateThread {
    public static void main(String[] args) {
        Thread t1 = new Thread();
        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println("==========");
            }
        };
        t1.start();
        t2.start();
        System.out.println(t1.getName());
        System.out.println(t2.getName());

        Thread t3 = new Thread("MyName");
        Thread t4 = new Thread(() -> {
            System.out.println("Runnable...");
        });

        System.out.println(t3.getName());
        System.out.println(t4.getName());

        Thread t5 = new Thread(() -> {
            System.out.println("Runnable..." + Thread.currentThread().getName());
        }, "RunnableThread");

        t5.start();
    }
}
public class CreateThread2 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t.start();
        System.out.println("==================");
        System.out.println(t.getThreadGroup());//java.lang.ThreadGroup[name=main,maxpri=10]
        System.out.println(Thread.currentThread().getName());//main
        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
        System.out.println(threadGroup.getName());//main
        System.out.println("==================");
        System.out.println(threadGroup.activeCount());//3

        Thread[] threads = new Thread[threadGroup.activeCount()];
        threadGroup.enumerate(threads);

        Arrays.asList(threads).forEach(System.out::println);
        //Thread[main,5,main]
        //Thread[Monitor Ctrl-Break,5,main]
        //Thread[Thread-0,5,]
    }
}
public class CreateThread3 {

    private int i = 0;

    private byte[] bytes = new byte[1024];

    private static int counter = 0;

    //JVM will create a thread named "main"
    public static void main(String[] args) {
        //create a JVM stack
        try {
            add(0);
        } catch (Error e) {
            e.printStackTrace();
            System.out.println(counter); //31457
        }
    }

    private static void add(int i) {
        ++counter;
        add(i + 1);
    }
   
}
public class CreateThread4 {

    private static int counter = 1;

    public static void main(String[] args) {

        Thread t1 = new Thread(null, new Runnable() {
            @Override
            public void run() {
                try {
                    add(1);
                } catch (Error e) {
                    System.out.println(counter);
                }
            }

            private void add(int i) {
                counter++;
                add(i + 1);
            }
        }, "Test", 1 << 24);
        t1.start();
        //260419
    }
}
public class CreateThread5 {

    private static int counter = 1;

    public static void main(String[] args) {

        try {
            for (int i = 0; i < 1000; i++) {
                counter++;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            add(1);
                        } catch (Error e) {
//                            System.out.println(counter);
                        }
                    }

                    private void add(int i) {

                        add(i + 1);
                    }
                }).start();
            }
        } catch (Error e) {
            counter++;
        }
        System.out.println("Total created thread nums=>" + counter);
    }
}

总结:

1、创建线程对象Thread,默认有一个线程名,以Thread-开头,从0开始计数

2、如果在构造Thread的时候没有传递Runnable或者没有复写Thread的run方法,该Thread将不会调用任何东西,如果传递了Runnable
接口的实例,或者复写了Thread的run方法,则会执行该方法的逻辑单元

3、如果构造线程对象时未传入ThreadGroup,Thread会默认获取父线程的ThreadGroup作为该线程的ThreadGroup,此时
子线程和父线程将会在同一个ThreadGroup中

4、构造Thread的时候传入stackSize代表着该线程占用的stack大小,如果没有指定stacksize的大小,
默认是0,0代表着会忽略该参数,该参数会被JNI函数去使用 。需要注意:该参数有一些平台有效,在有些平台则无效

例子6-守护线程

//守护线程

/**
 * A<---------------------------------->B
 *  ->daemonThread(health check)
 * */
public class DaemonThread {

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

        Thread t = new Thread() {

            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " running");
                    Thread.sleep(100000);
                    System.out.println(Thread.currentThread().getName() + " done.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }; //new
        t.setDaemon(true);
        //runnable  ->running| ->dead| ->blocked
        t.start();


        Thread.sleep(5_000);   //JDK1.7
        System.out.println(Thread.currentThread().getName());
    }
}
public class DaemonThread2 {
    public static void main(String[] args) {

        Thread t = new Thread(() -> {
            Thread innerThread = new Thread(() -> {
                try {
                    while (true) {
                        System.out.println("Do some thing for health check.");
                        Thread.sleep(1_000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

//            innerThread.setDaemon(true); 设置为守护线程,该线程会关闭
            innerThread.start();

            try {
                Thread.sleep(1_000);
                System.out.println("T thread finish done.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //t.setDaemon(true);
        t.start();


    }
}
public class ThreadSimpleAPI {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            Optional.of("Hello").ifPresent(System.out::println);
            try {
                Thread.sleep(100_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");

        t.start();
        Optional.of(t.getName()).ifPresent(System.out::println);
        Optional.of(t.getId()).ifPresent(System.out::println);
        Optional.of(t.getPriority()).ifPresent(System.out::println);
    }
}
//输出
t1
Hello
12
5
//线程优先级(并不是严格按照高中低执行的)
public class ThreadSimpleAPI2 {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });
        t1.setPriority(Thread.MAX_PRIORITY);

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });

        t2.setPriority(Thread.NORM_PRIORITY);

        Thread t3 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });

        t3.setPriority(Thread.MIN_PRIORITY);

        t1.start();
        t2.start();
        t3.start();
    }
}

例子7-join()

//join :join的线程全部运行完之后,别的线程才会开始运行
public class ThreadJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            IntStream.range(1, 1000)
                    .forEach(i -> System.out.println(Thread.currentThread().getName() + "->" + i));
        });
        Thread t2 = new Thread(() -> {
            IntStream.range(1, 1000)
                    .forEach(i -> System.out.println(Thread.currentThread().getName() + "->" + i));
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        Optional.of("All of tasks finish done.").ifPresent(System.out::println);
        IntStream.range(1, 1000)
                .forEach(i -> System.out.println(Thread.currentThread().getName() + "->" + i));
    }
}
//join(long millis, int nanos)
public class ThreadJoin2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                System.out.println("t1 is running");
                Thread.sleep(10_000);
                System.out.println("t1 is done");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t1.join(100,10);


        Optional.of("All of tasks finish done.").ifPresent(System.out::println);
        IntStream.range(1, 1000)
                .forEach(i -> System.out.println(Thread.currentThread().getName() + "->" + i));

        //start httpServer
//        JettyHttpServer.start();

//        Thread.currentThread().join();

//        Thread t1 = new Thread(() -> {
//
//            System.out.println("t1 is running");
//            while (true) {
//                System.out.println(Thread.currentThread().isInterrupted());
//            }
//        });
//        t1.start();
//        Thread t2 = new Thread(() -> {
//            try {
//                Thread.sleep(10000);
//                t1.interrupt();
//                System.out.println("interrupt");
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//
//        });
//        t2.start();
//
//        try {
//            t1.join(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }


    }
}

用join()写的一个例子:三个机器全部运行完成输出打印结果。

public class ThreadJoin3 {

    public static void main(String[] args) throws InterruptedException {
        long startTimestamp = System.currentTimeMillis();
        Thread t1 = new Thread(new CaptureRunnable("M1", 10000L));
        Thread t2 = new Thread(new CaptureRunnable("M2", 30000L));
        Thread t3 = new Thread(new CaptureRunnable("M3", 15000L));

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

        long endTimestamp = System.currentTimeMillis();
        System.out.printf("Save data begin timestamp is:%s, end timestamp is:%s\n", startTimestamp, endTimestamp);
    }

}

class CaptureRunnable implements Runnable {

    private String machineName;

    private long spendTime;

    public CaptureRunnable(String machineName, long spendTime) {
        this.machineName = machineName;
        this.spendTime = spendTime;
    }

    @Override
    public void run() {
        //do the really capture data.
        try {
            Thread.sleep(spendTime);
            System.out.printf(machineName + " completed data capture at timestamp [%s] and successfully.\n", System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getResult() {
        return machineName + " finish.";
    }
}

例子8-interrupt()

public class ThreadService {
    private Thread executeThread;
    private boolean finished = false;

    public void execute(Runnable task){
        executeThread = new Thread(() -> {
            Thread runner =  new Thread(task);
            runner.setDaemon(true);
            runner.start();
            try {
                runner.join();
                finished = true;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executeThread.start();
    }
    public void shutdown(long mills){
        long currentTime = System.currentTimeMillis();
        while (!finished){
            if ((System.currentTimeMillis() - currentTime) >= mills){
                System.out.println("任务超时,需要结束它");
                executeThread.interrupt();
                break;
            }
            try {
                executeThread.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("执行线程被打断!");
                break;
            }
        }
        finished = false;
    }

}
//线程强制关闭
public class ThreadCloseForce {
    public static void main(String[] args) {
        ThreadService service = new ThreadService();
        long start = System.currentTimeMillis();
        service.execute(()->{
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        service.shutdown(10000);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }

}
//优雅的关闭
public class ThreadCloseGraceful {
    private static class Worker extends Thread{
        private volatile boolean start = true;
        @Override
        public void run() {
            while (start){
                //
            }
        }
        public void shutdown(){
            this.start = false;
        }
    }

    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.start();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        worker.shutdown();
    }
}
//优雅的关闭2
public class ThreadCloseGraceful2 {
    private static class Worker extends Thread {
        @Override
        public void run() {
            while (true) {
                if (Thread.interrupted()) {
                    break;
                }
            }
        }

    }

    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        worker.interrupt();
    }
}
//interrupt的例子
public class ThreadInterrupt {

    private static final Object MONITOR = new Object();

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

       /* Thread t = new Thread() {
            @Override
            public void run() {
                while (true) {
                    synchronized (MONITOR) {
                        try {
                            MONITOR.wait(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            System.out.println(isInterrupted());
                        }
                    }
                }
            }
        };

        t.start();
        Thread.sleep(100);
        System.out.println(t.isInterrupted());//false
        t.interrupt();
        System.out.println(t.isInterrupted());//true

        t.stop();*/

//        Thread t = new Thread(() -> {
//            while (true) {
//                synchronized (MONITOR) {
//                    try {
//                        MONITOR.wait(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                        System.out.println(Thread.interrupted());
//                    }
//                }
//            }
//        });
            Thread t = new Thread() {
                @Override
                public void run() {
                    while (true) {

                    }
                }
            };

        t.start();
        Thread main = Thread.currentThread();
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                main.interrupt();
                System.out.println("interrupt");
            }
        };

        t2.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //---------------------------


    }
}

例子9

1、//this锁 锁住的是当前类

public class SynchronizedThis {
    public static void main(String[] args) {
        ThisLock thisLock = new ThisLock();
        new Thread(()-> thisLock.m1()).start();
        new Thread(()->thisLock.m2()).start();
    }
}
class ThisLock{
    private final Object LOCK = new Object();
    public void m1(){
        synchronized (this){
            try {
                System.out.println(Thread.currentThread().getName()+this.getClass());
                Thread.sleep(10_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void m2(){
        synchronized (this){
            try {
                System.out.println(Thread.currentThread().getName()+this.getClass());
                Thread.sleep(10_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2、//synchronized 测试类 顺序执行

public class SynchronizedTest {

    private final static Object LOCK = new Object();

    public static void main(String[] args) {

        Runnable runnable = () -> {
            synchronized (LOCK) {
                try {
                    Thread.sleep(2_000);
                    System.out.println(Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        Thread t3 = new Thread(runnable);
        t1.start();
        t2.start();
        t3.start();

    }
}

3、BankVersion2

public class BankVersion2 {

    public static void main(String[] args) {

        final TicketWindowRunnable ticketWindow = new TicketWindowRunnable();

        Thread windowThread1 = new Thread(ticketWindow, "一号窗口");
        Thread windowThread2 = new Thread(ticketWindow, "二号窗口");
        Thread windowThread3 = new Thread(ticketWindow, "三号窗口");
        windowThread1.start();
        windowThread2.start();
        windowThread3.start();
    }
}
public class TicketWindowRunnable implements Runnable {

    private final static Integer MAX = 500;

    private Integer index = 1;

    private final Object MONITOR = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (MONITOR) {
                if (index > MAX)
                    break;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + " 的号码为:" + index++);
            }

        }
    }
}

4、BankVersion3

public class BankVersion3 {
    public static void main(String[] args) {
        final SynchronizedRunnable ticketWindow = new SynchronizedRunnable();

        Thread windowThread1 = new Thread(ticketWindow, "一号窗口");
        Thread windowThread2 = new Thread(ticketWindow, "二号窗口");
        Thread windowThread3 = new Thread(ticketWindow, "三号窗口");
        windowThread1.start();
        windowThread2.start();
        windowThread3.start();
    }
}
public class SynchronizedRunnable implements Runnable {
    private int index = 1;
    //只读共享数据
    private final static int MAX = 500;

    //this
    @Override
    public void run() {
        while (true) {
            if (ticket()) {
                break;
            }
        }
    }

    //    private synchronized boolean ticket() {
//        if (index>MAX){
//            return true;
//        }
//        try {
//            Thread.sleep(5);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        System.out.println(Thread.currentThread() + " 的号码是:" + (index++));
//        return false;
//    }
    private boolean ticket() {
        synchronized (this) {

            if (index > MAX) {
                return true;
            }
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + " 的号码是:" + (index++));
            return false;
        }
    }
}

5、//静态同步代码块

public class SychronizedStaticTest {
    public static void main(String[] args) {
        new Thread("T1") {
            @Override
            public void run() {
                SynchronizedStatic.m1();
            }
        }.start();

        new Thread("T2") {
            @Override
            public void run() {
                SynchronizedStatic.m2();
            }
        }.start();

        new Thread("T3") {
            @Override
            public void run() {
                SynchronizedStatic.m3();
            }
        }.start();
    }
}

public class SynchronizedStatic {
    static {
        synchronized (SynchronizedStatic.class) {
            try {
                System.out.println("static " + Thread.currentThread().getName());
                Thread.sleep(10_000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized static void m1() {
        System.out.println("m1 " + Thread.currentThread().getName());
        try {
            Thread.sleep(10_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized static void m2() {
        System.out.println("m2 " + Thread.currentThread().getName());
        try {
            Thread.sleep(10_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void m3() {
        System.out.println("m3 " + Thread.currentThread().getName());
        try {
            Thread.sleep(10_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
输出
static T1
m1 T1
m3 T3
m2 T2
**/

例子10-deadLock

/**
死锁例子
查看方式:jps
 jstack 端口
 */
public class DeadLockExample {
    public static void main(String[] args) {
        deadLock();
    }

    private static void deadLock() {
        final Object OBJ1 = new Object();
        final Object OBJ2 = new Object();
        new Thread(() -> {
            synchronized (OBJ1) {
                System.out.println("获取obj1成功");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (OBJ2) {
                    System.out.println("获取obj2成功");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (OBJ2) {
                System.out.println("获取obj2成功");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (OBJ1) {
                    System.out.println("获取obj1成功");
                }
            }
        }).start();
    }

}

//自定义deadLock
public class OtherService {
    private final Object lock = new Object();
    private DeadLock deadLock;
    public void s1() {
        synchronized (lock){
            System.out.println("s1========");
        }
    }
    public void s2(){
        synchronized (lock){
            System.out.println("s2====");
            deadLock.m2();
        }
    }

    public void setDeadLock(DeadLock deadLock) {
        this.deadLock = deadLock;
    }
}
public class DeadLock {
    private OtherService otherService;

    public DeadLock(OtherService otherService) {
        this.otherService = otherService;
    }

    private final Object lock = new Object();

    public void m1() {
        synchronized (lock) {
            System.out.println("m1");
            otherService.s1();
        }
    }

    public void m2() {
        synchronized (lock) {
            System.out.println("m2");
        }
    }
}


public class DeadLockTest {
    public static void main(String[] args) {
        OtherService otherService = new OtherService();
        DeadLock deadLock = new DeadLock(otherService);
        otherService.setDeadLock(deadLock);
        new Thread(() -> {
            while (true) {
                deadLock.m1();
            }
        }).start();

        new Thread(() -> {
            while (true)
                otherService.s2();
        }).start();
    }
}

例子11

/**
 * 采集sevice
 * 同时工作的线程不超过5个
 */
public class CaptureService {
    private final static LinkedList<Control> CONTROLS = new LinkedList();
    private final static Integer MAX_WORKER = 5;

    public static void main(String[] args) {
        List<Thread> worker = new ArrayList<>();
        Arrays.asList("M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9", "M10").stream()
                .map(CaptureService::createCaptureThread).forEach(
                        t->{
                            t.start();
                            worker.add(t);
                        }
        );
        worker.stream().forEach(
                t->{
                    try {
                        t.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        );
        Optional.of("All of capture work finished").ifPresent(System.out::println);
    }

    private static Thread createCaptureThread(String name) {
        return new Thread(()->{
            Optional.of("The worker [" + Thread.currentThread().getName() + "] BEGIN capture data.")
                    .ifPresent(System.out::println);
            synchronized (CONTROLS){
                while (CONTROLS.size()>MAX_WORKER){
                    try {
                        CONTROLS.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                CONTROLS.addLast(new Control());;
            }
            Optional.of("The worker [" + Thread.currentThread().getName() + "] is working...")
                    .ifPresent(System.out::println);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (CONTROLS){
                Optional.of("The worker [" + Thread.currentThread().getName() + "] END capture data.")
                        .ifPresent(System.out::println);
                CONTROLS.removeFirst();
                CONTROLS.notifyAll();
            }
        },name);
    }

}
class Control{

}

wait和sleep的不同

public class DifferenceOfWaitAndSleep {

    private final static Object LOCK = new Object();

    public static void main(String[] args) {
        Stream.of("T1", "T2").forEach(name ->
                new Thread(name) {
                    @Override
                    public void run() {
                        m2();
                    }
                }.start()
        );
    }

    public static void m1() {
        synchronized (LOCK) {
            try {
                System.out.println("The Thread " + Thread.currentThread().getName() + " enter.");
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void m2() {
        synchronized (LOCK) {
            try {
                System.out.println("The Thread " + Thread.currentThread().getName() + " enter.");
                LOCK.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

生产者消费者问题1(生产完没告诉我,也不知道是不是最新的)

public class ProduceConsumerVersion1 {
    private int i = 1;

    final private Object LOCK = new Object();

    private void produce() {
        synchronized (LOCK) {
            System.out.println("P->" + (i++));
        }
    }

    private void consume() {
        synchronized (LOCK) {
            System.out.println("C->" + i);
        }
    }

    public static void main(String[] args) {

        ProduceConsumerVersion1 pc = new ProduceConsumerVersion1();

        new Thread("P") {
            @Override
            public void run() {
                while (true)
                    pc.produce();
            }
        }.start();

        new Thread("C") {
            @Override
            public void run() {
                while (true)
                    pc.consume();
            }
        }.start();
    }
}

生产者消费者2(多线程下有问题)假死:都放弃了CP执行权 wait了

public class ProduceConsumerVersion2 {
    private int i = 0;

    private final Object LOCK = new Object();

    private volatile boolean isProduce = false;

    public void produce() {
        synchronized (LOCK){
            if (isProduce){
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                i++;
                System.out.println("P->"+i);
                LOCK.notify();
                isProduce = true;
            }
        }
    }
    public void consume(){
        synchronized (LOCK){
            if (isProduce){
                System.out.println("C->"+i);
                LOCK.notify();
                isProduce = false;
            }else{
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();
        Stream.of("P1","P2").forEach(
                n-> new Thread(n){
                    @Override
                    public void run() {
                        while (true)
                            pc.produce();
                    }
                }.start()
        );
        Stream.of("C1","C2").forEach(
                n-> new Thread(n){
                    @Override
                    public void run() {
                        while (true)
                            pc.consume();
                    }
                }.start()
        );
    }
}

生产者消费者3 (多线程完整版)

//
public class ProduceConsumerVersion3 {
    private int i = 0;

    private final Object LOCK = new Object();

    private volatile boolean isProduce = false;

    public void produce() {
        synchronized (LOCK) {
            while (isProduce) {
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            i++;
            System.out.println("P->" + i);
            LOCK.notifyAll();
            isProduce = true;

        }
    }

    public void consume() {
        synchronized (LOCK) {
            while (!isProduce) {
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            System.out.println("C->" + i);
            LOCK.notify();
            isProduce = false;

        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion3 pc = new ProduceConsumerVersion3();
        Stream.of("P1", "P2").forEach(
                n -> new Thread(n) {
                    @Override
                    public void run() {
                        while (true) {
                            pc.produce();
                            try {
                                Thread.sleep(1);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start()
        );
        Stream.of("C1", "C2").forEach(
                n -> new Thread(n) {
                    @Override
                    public void run() {
                        while (true){
                            pc.consume();
                            try {
                                Thread.sleep(1);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start()
        );
    }
}

sleep()和wait()的区别:
1.sleep()是Thread()的方法,而wait()是Object()的方法
2.sleep()不会释放Object的监控,而wait()会释放监控并把Object monitor加到队列中
3.sleep()不依赖monitor,而wait()需要
4.sleep()不需要wakeup,而wait()需要

例子12-自定义lock锁

public interface Lock {
    class TimeOutException extends Exception {
        public TimeOutException(String message) {
            super(message);
        }
    }

    void lock() throws InterruptedException;

    void lock(long mills) throws InterruptedException, TimeOutException;

    void unlock();

    Collection<Thread> getBlockedThread();

    int getBlockedSize();
}

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

public class BooleanLock implements Lock {

    private boolean initValue;
    private Collection<Thread> blockedThreadCollection = new ArrayList<>();
    private Thread currentThread;

    public BooleanLock() {
        this.initValue = false;
    }

    @Override
    public synchronized void lock() throws InterruptedException {
        while (initValue){
            blockedThreadCollection.add(Thread.currentThread());
            this.wait();
        }
        blockedThreadCollection.remove(Thread.currentThread());
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
        if (mills <=0){
            lock();
        }
        long hasRemaining = mills;
        long endTime = System.currentTimeMillis() + mills;
        while (initValue){
            if (hasRemaining<=0){
                throw new TimeOutException("Time Out");
            }
            blockedThreadCollection.add(Thread.currentThread());
            this.wait(mills);
            hasRemaining= endTime - System.currentTimeMillis();
        }
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void unlock() {
        if (Thread.currentThread() == currentThread){
            this.initValue = false;
            Optional.of(Thread.currentThread().getName() + " release the lock monitor.")
                    .ifPresent(System.out::println);
            this.notifyAll();
        }
    }

    @Override
    public Collection<Thread> getBlockedThread() {
        return Collections.unmodifiableCollection(blockedThreadCollection);
    }

    @Override
    public int getBlockedSize() {
        return blockedThreadCollection.size();
    }
}
import java.util.Optional;
import java.util.stream.Stream;

public class LockTest {
    public static void main(String[] args) throws InterruptedException {

        final BooleanLock booleanLock = new BooleanLock();
        Stream.of("T1", "T2", "T3", "T4")
                .forEach(name ->
                        new Thread(() -> {
                            try {
                                booleanLock.lock(100L);
                                Optional.of(Thread.currentThread().getName() + " have the lock Monitor")
                                        .ifPresent(System.out::println);
                                work();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } catch (Lock.TimeOutException e) {
                                Optional.of(Thread.currentThread().getName() + " time out")
                                        .ifPresent(System.out::println);
                            } finally {
                                booleanLock.unlock();
                            }
                        }, name).start()
                );
    }

    private static void work() throws InterruptedException {
        Optional.of(Thread.currentThread().getName() + " is Working...")
                .ifPresent(System.out::println);
        Thread.sleep(4_000);
    }
}

例子13 -线程发生异常怎么捕获

//Thread对发生异常的捕获
public class ThreadException {
    private final static int A = 10;
    private final static int B = 0;


    public static void main(String[] args) {

//        new Test1().test();

        Thread t = new Thread(() -> {
            try {
                Thread.sleep(5_000L);
                int result = A / B;
                System.out.println(result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t.setUncaughtExceptionHandler((thread, e) -> {
            System.out.println(e);
            System.out.println(thread);
        });

        t.start();
    }
}

public class Test1
{

    private Test2 test2 = new Test2();

    public void test(){
        test2.test();
    }
}

public class Test2 {

    public void test() {
        Arrays.asList(Thread.currentThread().getStackTrace()).stream()
                .filter(e->!e.isNativeMethod())
                .forEach(e-> Optional.of(e.getClassName()+":"+e.getMethodName()+":"+e.getLineNumber())
                .ifPresent(System.out::println));
    }
}

例子14-ThreadGroup

创建ThreadGroup

public class ThreadGroupCreate {

    public static void main(String[] args) {
        //use the name

        ThreadGroup tg1 = new ThreadGroup("TG1");
        Thread t1 = new Thread(tg1, "t1") {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println(getThreadGroup().getName());//TG1
                        System.out.println(getThreadGroup().getParent());//java.lang.ThreadGroup[name=main,maxpri=10]
                        System.out.println(getThreadGroup().getParent().activeCount());//3
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t1.start();

        System.out.println("===============");
        ThreadGroup tg2 = new ThreadGroup("TG2");
        Thread t2 = new Thread(tg2, "T2") {
            @Override
            public void run() {
                System.out.println(">>>"+tg1.getName());//>>>TG1
                Thread[] threads = new Thread[tg1.activeCount()];
                tg1.enumerate(threads);
                System.out.println("+++");
                Arrays.asList(threads).forEach(System.out::println);//Thread[t1,5,TG1]
            }
        };

        t2.start();

        System.out.println(tg2.getName());//TG2
        System.out.println(tg2.getParent());//java.lang.ThreadGroup[name=main,maxpri=10]


        System.out.println(Thread.currentThread().getName());//main
        System.out.println(Thread.currentThread().getThreadGroup().getName());//main
    }
}

ThreadAPI

public class ThreadGroupAPI {
    public static void main(String[] args) throws InterruptedException {

        ThreadGroup tg1 = new ThreadGroup("TG1");
        Thread t1 = new Thread(tg1, "t1") {
            @Override
            public void run() {
                while (true) {
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
                }
            }
        };

//        tg1.setDaemon(true);
        t1.start();
//        Thread.sleep(2_000);
//        System.out.println(tg1.isDestroyed());
//        tg1.destroy();
//        System.out.println(tg1.isDestroyed());
//
        ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
        Thread t2 = new Thread(tg2, "T2") {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        };

        t2.start();

        System.out.println(tg1.activeCount());
        System.out.println(tg1.activeGroupCount());
        t2.checkAccess();
//        tg1.destroy();

        System.out.println("=========================");
        Thread[] ts1 = new Thread[tg1.activeCount()];
        tg1.enumerate(ts1);
        Arrays.asList(ts1).forEach(System.out::println);

        System.out.println("=========================");
        tg1.enumerate(ts1, true);
        Arrays.asList(ts1).forEach(System.out::println);

        System.out.println("=========================");
        ts1 = new Thread[10];
        Thread.currentThread().getThreadGroup().enumerate(ts1, false);
        Arrays.asList(ts1).forEach(System.out::println);

        tg1.interrupt();

    }
}

简单的线程池

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class SimpleThreadPool extends Thread {

    private int size;

    private final int queueSize;

    private final static int DEFAULT_TASK_QUEUE_SIZE = 2000;

    private static volatile int seq = 0;

    private final static String THREAD_PREFIX = "SIMPLE_THREAD_POOL-";

    private final static ThreadGroup GROUP = new ThreadGroup("Pool_Group");

    private final static LinkedList<Runnable> TASK_QUEUE = new LinkedList<>();

    private final static List<WorkerTask> THREAD_QUEUE = new ArrayList<>();

    private final DiscardPolicy discardPolicy;

    public final static DiscardPolicy DEFAULT_DISCARD_POLICY = () -> {
        throw new DiscardException("Discard This Task.");
    };

    private volatile boolean destroy = false;

    private int min;

    private int max;

    private int active;

    public SimpleThreadPool() {
        this(4, 8, 12, DEFAULT_TASK_QUEUE_SIZE, DEFAULT_DISCARD_POLICY);
    }

    public SimpleThreadPool(int min, int active, int max, int queueSize, DiscardPolicy discardPolicy) {
        this.min = min;
        this.active = active;
        this.max = max;
        this.queueSize = queueSize;
        this.discardPolicy = discardPolicy;
        init();
    }

    private void init() {
        for (int i = 0; i < this.min; i++) {
            createWorkTask();
        }
        this.size = min;
        this.start();
    }

    public void submit(Runnable runnable) {
        if (destroy)
            throw new IllegalStateException("The thread pool already destroy and not allow submit task.");

        synchronized (TASK_QUEUE) {
            if (TASK_QUEUE.size() > queueSize)
                discardPolicy.discard();
            TASK_QUEUE.addLast(runnable);
            TASK_QUEUE.notifyAll();
        }
    }

    @Override
    public void run() {
        while (!destroy) {
            System.out.printf("Pool#Min:%d,Active:%d,Max:%d,Current:%d,QueueSize:%d\n",
                    this.min, this.active, this.max, this.size, TASK_QUEUE.size());
            try {
                Thread.sleep(5_000L);
                if (TASK_QUEUE.size() > active && size < active) {
                    for (int i = size; i < active; i++) {
                        createWorkTask();
                    }
                    System.out.println("The pool incremented to active.");
                    size = active;
                } else if (TASK_QUEUE.size() > max && size < max) {
                    for (int i = size; i < max; i++) {
                        createWorkTask();
                    }
                    System.out.println("The pool incremented to max.");
                    size = max;
                }

                synchronized (THREAD_QUEUE) {
                    if (TASK_QUEUE.isEmpty() && size > active) {
                        System.out.println("=========Reduce========");
                        int releaseSize = size - active;
                        for (Iterator<WorkerTask> it = THREAD_QUEUE.iterator(); it.hasNext(); ) {
                            if (releaseSize <= 0)
                                break;

                            WorkerTask task = it.next();
                            task.close();
                            task.interrupt();
                            it.remove();
                            releaseSize--;
                        }
                        size = active;
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void createWorkTask() {
        WorkerTask task = new WorkerTask(GROUP, THREAD_PREFIX + (seq++));
        task.start();
        THREAD_QUEUE.add(task);
    }

    public void shutdown() throws InterruptedException {
        while (!TASK_QUEUE.isEmpty()) {
            Thread.sleep(50);
        }

        synchronized (THREAD_QUEUE) {
            int initVal = THREAD_QUEUE.size();
            while (initVal > 0) {
                for (WorkerTask task : THREAD_QUEUE) {
                    if (task.getTaskState() == TaskState.BLOCKED) {
                        task.interrupt();
                        task.close();
                        initVal--;
                    } else {
                        Thread.sleep(10);
                    }
                }
            }
        }

        System.out.println(GROUP.activeCount());

        this.destroy = true;
        System.out.println("The thread pool disposed.");
    }

    public int getQueueSize() {
        return queueSize;
    }

    public int getSize() {
        return size;
    }

    public boolean isDestroy() {
        return this.destroy;
    }

    public int getMin() {
        return min;
    }

    public int getMax() {
        return max;
    }

    public int getActive() {
        return active;
    }

    private enum TaskState {
        FREE, RUNNING, BLOCKED, DEAD
    }

    public static class DiscardException extends RuntimeException {

        public DiscardException(String message) {
            super(message);
        }
    }

    public interface DiscardPolicy {

        void discard() throws DiscardException;
    }

    private static class WorkerTask extends Thread {

        private volatile TaskState taskState = TaskState.FREE;

        public WorkerTask(ThreadGroup group, String name) {
            super(group, name);
        }

        public TaskState getTaskState() {
            return this.taskState;
        }

        public void run() {
            OUTER:
            while (this.taskState != TaskState.DEAD) {
                Runnable runnable;
                synchronized (TASK_QUEUE) {
                    while (TASK_QUEUE.isEmpty()) {
                        try {
                            taskState = TaskState.BLOCKED;
                            TASK_QUEUE.wait();
                        } catch (InterruptedException e) {
                            System.out.println("Closed.");
                            break OUTER;
                        }
                    }
                    runnable = TASK_QUEUE.removeFirst();
                }

                if (runnable != null) {
                    taskState = TaskState.RUNNING;
                    runnable.run();
                    taskState = TaskState.FREE;
                }
            }
        }

        public void close() {
            this.taskState = TaskState.DEAD;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SimpleThreadPool threadPool = new SimpleThreadPool();
        for (int i = 0; i < 40; i++) {
            threadPool.submit(() -> {
                System.out.println("The runnable  be serviced by " + Thread.currentThread() + " start.");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("The runnable be serviced by " + Thread.currentThread() + " finished.");
            });
        }

        Thread.sleep(10000);
        threadPool.shutdown();

       /* Thread.sleep(10000);
        threadPool.shutdown();
        threadPool.submit(() -> System.out.println("======="));*/
    }
}
├─第一阶段 │      源码+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讲、介绍三种效优雅的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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值