0
点赞
收藏
分享

微信扫一扫

【SpringBoot源码剥析】| 依赖管理

ivy吖 2023-05-06 阅读 71

今日内容

零、 复习昨日

一、作业

售卖后车票

见代码

二、线程安全的类[了解]

image-20230303094122011

image-20230303094159112

image-20230303094527278

image-20230303095012216

三、死锁[了解]

public class MyLock {
    // 左筷子锁
    static Object zuo = new Object();
    // 右筷子锁
    static Object you = new Object();

}
public class Girl extends Thread{

    @Override
    public void run() {
        synchronized (MyLock.zuo) {
            System.out.println("女朋友获得左筷子" );
            synchronized (MyLock.you) {
                System.out.println("女朋友获得右筷子-吃饭" );
            }
        }
    }
}
public class Boy extends Thread{

    @Override
    public void run() {
        synchronized (MyLock.you) {
            System.out.println("男朋友获得右筷子" );
            synchronized (MyLock.zuo) {
                System.out.println("男朋友获得右左筷子-吃饭" );
            }
        }
    }
}
public class TestDeadLock {
    public static void main(String[] args) {
        new Boy().start();
        new Girl().start();
    }
}

四、线程通信[熟悉]

4.1 介绍

4.2 两个个线程通信

需求: 昨天打印机方法,让print1()和print2()方法交替执行

package com.qf.notify;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 通信
 */
public class Printer {

    /**
     * 打印机执行的标志
     * 此标志如果是1,说明该打印机1执行,否则打印机1停下
     * 此标志如果是2,说明该打印机2执行,否则打印机2停下
     */
    private int flag = 1;

    public synchronized void print1() throws InterruptedException {
        if (flag != 1) { // 判断不是自己执行时
            // 线程停下不执行
            // 锁对象是谁,谁去wait方法
            this.wait();
        }
        System.out.print("1 " );
        System.out.print("2 " );
        System.out.print("3 " );
        System.out.print("4 " );
        System.out.print("\r\n" );

        // 改变标志
        flag = 2;
        // 通知其他处于等待状态的线程,起来干活
        // 锁对象是谁,谁去notify方法
        this.notify();
    }

    public synchronized void print2() throws InterruptedException {
        if ( flag != 2) {
            this.wait();
        }
        System.out.print("A " );
        System.out.print("B " );
        System.out.print("C " );
        System.out.print("D " );
        System.out.print("\r\n" );

        flag = 1;
        this.notify();
    }
}
public class TestNotify {
    public static void main(String[] args) {
        Printer printer = new Printer( );

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        printer.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace( );
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        printer.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace( );
                    }
                }
            }
        }.start();
    }
}
package com.qf.notify;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 通信
 */
public class Printer2 {
    Object obj = new Object();

    private int flag = 1;

    public void print1() throws InterruptedException {
        synchronized (obj) {
            if (flag != 1) { // 判断不是自己执行时
                // 线程停下不执行
                // 锁对象是谁,谁去wait方法
                obj.wait( );
            }
            System.out.print("1 ");
            System.out.print("2 ");
            System.out.print("3 ");
            System.out.print("4 ");
            System.out.print("\r\n");

            // 改变标志
            flag = 2;
            // 通知其他处于等待状态的线程,起来干活
            // 锁对象是谁,谁去notify方法
            obj.notify( );
        }
    }

    public void print2() throws InterruptedException {
        synchronized (obj) {
            if (flag != 2) {
                obj.wait( );
            }
            System.out.print("A ");
            System.out.print("B ");
            System.out.print("C ");
            System.out.print("D ");
            System.out.print("\r\n");

            flag = 1;
            obj.notify( );
        }
    }
}

4.3 练习

创建A1 A2 两个线程,分别打印1-10,11-20,保证A1执行完再 执行A2线程,A2执行完再执行A1

A1 —> 1
A2 —>11
A1 —> 2
A2 —>12

package com.qf.notify;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class TestA1A2 {

    static int flag = 1;

    public static void main(String[] args) {
        Object o = new Object( );
        new Thread( ) {
            @Override
            public void run() {
                for (int i = 1; i < 11; i++) {
                    synchronized (o) {
                        if (flag != 1) {
                            try {
                                o.wait( );
                            } catch (InterruptedException e) {
                                e.printStackTrace( );
                            }
                        }
                        System.out.println("A1 -->" + i);
                        flag = 2;
                        o.notify( );
                    }
                }
            }
        }.start( );

        new Thread( ) {
            @Override
            public void run() {
                for (int i = 11; i < 21; i++) {
                    synchronized (o) {
                        if (flag != 2) {
                            try {
                                o.wait( );
                            } catch (InterruptedException e) {
                                e.printStackTrace( );
                            }
                        }
                        System.out.println("A2 -->" + i);
                        flag = 1;
                        o.notify( );
                    }
                }
            }
        }.start( );
    }
}

4.4 三个线程的通信

如果是notify

解决方案: 全部唤醒 ,使用方法notifyAll(),唤醒所有处于等待状态的线程

package com.qf.notify;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Printer {

    int flag = 1;

    public synchronized void print1() throws Exception{
        while (flag != 1) {
            this.wait();// 哪里等待,被唤醒后继续执行,
            // 将此处的if改成while,目的是让线程唤醒后继续回头再判断一次
        }
        System.out.print("1 ");
        System.out.print("2 ");
        System.out.print("3 ");
        System.out.print("4 ");
        System.out.print("\r\n");

        flag = 2;
        //this.notify();// 随机唤醒处于等待状态的一条线程
        this.notifyAll();// 唤醒全部处于等待状态的线程

    }

    public synchronized void print2() throws Exception{
        while (flag != 2) {
            this.wait();
        }
        System.out.print("A ");
        System.out.print("B ");
        System.out.print("C ");
        System.out.print("D ");
        System.out.print("\r\n");

        flag = 3;
        this.notifyAll();

    }

    public synchronized void print3() throws Exception{
        while (flag != 3) {
            this.wait();
        }
        System.out.print("一 ");
        System.out.print("二 ");
        System.out.print("三 ");
        System.out.print("四 ");
        System.out.print("\r\n");

        flag = 1;
        this.notifyAll();
    }
}

4.5 总结

五、生产者消费者

package com.qf.pc;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 商品
 */
public class Phone {
    private String desc;

    public Phone(String desc) {
        this.desc = desc;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "desc='" + desc + '\'' +
                '}';
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
package com.qf.pc;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Shop {

    private Phone phone;

    // 进货(生产)
    public synchronized void product(Phone phone) {
        if (this.phone != null) {// 如果商店还有手机,暂时等待消费先不生产
            try {
                //System.out.println("商店有手机,请来消费" );
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }

        // 如果商店没手机,就生产
        this.phone = phone;
        System.out.println("生产中...." );
        // 通知消费
        this.notify();
    }
    // 消费
    public synchronized void consumer() {
        if (this.phone == null) {// 商店没有手机,等待生产
            try {
                //System.out.println("商店没有手机,请赶紧生产...");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }

        // 消费完,手机就没啦
        this.phone = null;
        System.out.println("消费中..." );
        // 通知生产
        this.notify();

    }

    public static void main(String[] args) {
        Shop shop = new Shop( );
        new Thread(){ // 一个线程生产
            @Override
            public void run() {
                for (int i = 1; i < 10; i++) {
                    shop.product(new Phone("XIAOMI"+i));
                }
            }
        }.start();

        new Thread(){ // 一个线程消费
            @Override
            public void run() {
                for (;;) {
                    shop.consumer();
                }
            }
        }.start();
    }
}

六、线程池

6.1 线程池概念

6.2 线程池原理

image-20230301230326324

6.3 创建线程池的方式

使用线程池创建线程,执行任务

6.4 不同特点的线程池

线程池执行任务时,可以采用两种方法:

package com.qf.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class TestThreadPool {
    public static void main(String[] args) {

        ExecutorService threadPool = Executors.newSingleThreadExecutor( );

        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable( ) {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"执行任务" );
                }
            });
        }

        threadPool.shutdown();

    }

    private static void show3() {
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);

        // execute这样没有定时执行
        // threadPool.execute(new Runnable( ) {
        //     @Override
        //     public void run() {
        //         System.out.println(Thread.currentThread().getName()+"执行任务" );
        //     }
        // });
        /**
         * schedule(Runnable r,long delay,TimeUnit 单位)
         */
        for (int i = 0; i < 3; i++) {
            threadPool.schedule(new Runnable( ) {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"执行任务" );
                }
            },3, TimeUnit.SECONDS);
        }

        threadPool.shutdown();
    }

    private static void show2() {
        // 创建缓冲线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool( );
        for (int i = 0; i < 5000; i++) {
            cachedThreadPool.execute(new Runnable( ) {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"执行任务..." );
                }
            });
        }

        cachedThreadPool.shutdown();
    }

    /**
     * 固定大小线程池
     */
    private static void show1() {
        // 使用工具类来创建不同类型的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);


        // 执行任务
        // void execute()
        // Future submit()
        for (int i = 1; i < 41; i++) {
            fixedThreadPool.execute(new Runnable( ) {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"在执行..." );
                }
            });
        }

        // 线程池关闭
        fixedThreadPool.shutdown();
    }
}

6.5 ThreadPoolExecutor[重要]

问: 什么是创建临时线程?
答: 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建线程

问:什么时候开始拒绝任务?
答:核心线程和临时线程都在忙,任务队列也满了,新的任务过来就会拒绝

public static void main(String[] args) {
    ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
    // new ThreadPoolExecutor(
    //        5,// 核心线程数
    //        15,// 最大线程数
    //        1, // 存活时间
    //        TimeUnit.MINUTES,
    //         queue,// 任务队列
    //         Executors.defaultThreadFactory(),// 默认的工厂
    //         new ThreadPoolExecutor.AbortPolicy());// 拒绝策略

    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        5,// 核心线程数
        15,// 最大线程数
        1, // 存活时间
        TimeUnit.MINUTES,
        queue// 任务队列
    );

    for (int i = 0; i < 45; i++) {
        threadPoolExecutor.execute(new Runnable( ) {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"执行..." );
            }
        });
    }

    System.out.println(queue );
    System.out.println(queue.size() );
}
举报

相关推荐

0 条评论