java进阶教程:2023.3.19第二十一天,java进阶多线程[java教程]

前言

记录时间:2023.3.19

已坚持的第二十一天

java从入门到精通

学习java时间历程记录打卡

早上6:00到 12:00

下午1:00到 6: 30

完成代码练习

d6_thread_synchronized_lock

1.定义类

package cn.vqqc.d6_thread_synchronized_lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 账户类:余额 , 卡号
 */
public class Account {
    private String cardId;
    private double money; // 余额 关键信息
    // final修饰后:锁对象是唯一和不可替换的,非常专业
    private final Lock lock = new ReentrantLock();

    public Account() {
    }

    public Account(String cardId, double money) {
        this.cardId = cardId;
        this.money = money;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    /**
     小明 小红
     */
    public void drawMoney(double money) {
        // 1、拿到是谁来取钱
        String name = Thread.currentThread().getName();
        // 2、判断余额是否足够
        // 小明  小红
        lock.lock(); // 上锁
        try {
            if(this.money >= money){
                // 钱够了
                System.out.println(name+"来取钱,吐出:" + money);
                // 更新余额
                this.money -= money;
                System.out.println(name+"取钱后,余额剩余:" + this.money);
            }else{
                // 3、余额不足
                System.out.println(name+"来取钱,余额不足!");
            }
        } finally {
            lock.unlock(); // 解锁
        }

    }
}

2.线程类

package cn.vqqc.d6_thread_synchronized_lock;

/**
 线程类
 */
public class DrawThread extends Thread{
    private Account acc;
    public DrawThread(Account acc, String name){
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        // 小明 小红  : acc
        acc.drawMoney(100000);
    }
}

3.测试线程安全问题

package cn.vqqc.d6_thread_synchronized_lock;

public class TestSafeDemo {
    public static void main(String[] args) {
        // 测试线程安全问题
        // 1、创建一个共享的账户对象。
        Account acc = new Account("ICBC-111" , 100000);

        // 2、创建2个线程对象,操作同一个账户对象
        new DrawThread(acc, "小明").start();
        new DrawThread(acc,"小红").start();

    }
}

d7_thread_comunication

1.呼叫系统

package cn.vqqc.d7_thread_comunication;

/**
 呼叫系统
 */
public class CallSystem {
    // 定义一个变量记录当前呼入进来的电话。
    public static int number = 0; // 最多只接听一个

    /* 接入电话
     */
    public synchronized static void call() {
        try {
            number++;
            System.out.println("成功接入一个用户,等待分发");

            // 唤醒别人 : 1个
            CallSystem.class.notify();
            // 让当前线程对象进入等待状态。
            CallSystem.class.wait();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     分发电话
     */
    public synchronized static void receive() {
        try {
            String name = Thread.currentThread().getName();
            if(number == 1){
                System.out.println(name + "此电话已经分发给客服并接听完毕了");
                number--;
                // 唤醒别人 : 1个
                CallSystem.class.notify();
                CallSystem.class.wait(); // 让当前线程等待
            }else {
                // 唤醒别人 : 1个
                CallSystem.class.notify();
                CallSystem.class.wait(); // 让当前线程等待
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.定义类

package cn.vqqc.d7_thread_comunication;

public class CallThread extends Thread{
    @Override
    public void run() {
        // 不断的打入电话
        while (true){
            CallSystem.call();
        }
    }
}

3.接电话线程类

package cn.vqqc.d7_thread_comunication;

/**
 接电话线程类
 */
public class ReceiveThread extends Thread{
    @Override
    public void run() {
        // 1号  2号
        while (true){
            CallSystem.receive();
        }
    }
}

4.接电话线程案例

package cn.vqqc.d7_thread_comunication;

public class TestDemo {
    public static void main(String[] args) {
        // 1、生产者线程:负责不断接收打进来的电话
        CallThread call = new CallThread();
        call.start();

        // 2、消费者线程:客服,每个客服每次接听一个电话
        ReceiveThread r1 = new ReceiveThread();
        r1.start();
    }
}

d8_threadpool

1.定义一个任务类 实现Callable接口

package cn.vqqc.d8_threadpool;

import java.util.concurrent.Callable;

/**
 1、定义一个任务类 实现Callable接口  应该申明线程任务执行完毕后的结果的数据类型
 */
public class MyCallable implements Callable<String>{
    private int n;
    public MyCallable(int n) {
        this.n = n;
    }

    /**
     2、重写call方法(任务方法)
     */
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n ; i++) {
            sum += i;
        }
        return Thread.currentThread().getName()
                + "执行 1-" + n+ "的和,结果是:" + sum;
    }
}

2.定义类

package cn.vqqc.d8_threadpool;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "输出了:HelloWorld ==> "  + i);
        }
        try {
            System.out.println(Thread.currentThread().getName() + "本任务与线程绑定了,线程进入休眠了~~~");
            Thread.sleep(10000000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.自定义一个线程池对象案例1

package cn.vqqc.d8_threadpool;

import java.util.concurrent.*;

/**
 目标:自定义一个线程池对象,并测试其特性
 */
public class ThreadPoolDemo1 {
    public static void main(String[] args) {
        // 1、创建线程池对象
        /**
         public ThreadPoolExecutor(int corePoolSize,
         int maximumPoolSize,
         long keepAliveTime,
         TimeUnit unit,
         BlockingQueue<Runnable> workQueue,
         ThreadFactory threadFactory,
         RejectedExecutionHandler handler)
         */
        ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
                6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy() );

        // 2、给任务线程池处理。
        Runnable target = new MyRunnable();
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);

        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);

        // 创建临时线程
        pool.execute(target);
        pool.execute(target);
//        // 不创建,拒绝策略被触发!!!
//        pool.execute(target);

        // 关闭线程池(开发中一般不会使用)。
        // pool.shutdownNow(); // 立即关闭,即使任务没有完成,会丢失任务的!
        pool.shutdown(); // 会等待全部任务执行完毕之后再关闭(建议使用的)
    }
}

4.自定义一个线程池对象案例2

package cn.vqqc.d8_threadpool;
import java.util.concurrent.*;

/**
 目标:自定义一个线程池对象,并测试其特性。
 */
public class ThreadPoolDemo2 {
    public static void main(String[] args) throws Exception {
        // 1、创建线程池对象
        /**
         public ThreadPoolExecutor(int corePoolSize,
         int maximumPoolSize,
         long keepAliveTime,
         TimeUnit unit,
         BlockingQueue<Runnable> workQueue,
         ThreadFactory threadFactory,
         RejectedExecutionHandler handler)
         */
        ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
                6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy() );

        // 2、给任务线程池处理。
        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));
        Future<String> f3 = pool.submit(new MyCallable(300));
        Future<String> f4 = pool.submit(new MyCallable(400));
        Future<String> f5 = pool.submit(new MyCallable(500));

//        String rs = f1.get();
//        System.out.println(rs);

        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());
        System.out.println(f5.get());
    }
}

5.使用Executors的工具方法直接得到一个线程池对象

package cn.vqqc.d8_threadpool;

import java.util.concurrent.*;

/**
 目标:使用Executors的工具方法直接得到一个线程池对象
 */
public class ThreadPoolDemo3 {
    public static void main(String[] args) throws Exception {
        // 1、创建固定线程数据的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable()); // 已经没有多余线程了
    }
}

d9_timer

1.Timer定时器的使用和了解

package cn.vqqc.d9_timer;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 目标:Timer定时器的使用和了解
 */
public class TimerDemo1 {
    public static void main(String[] args) {
        // 1、创建Timer定时器
        Timer timer = new Timer();  // 定时器本身就是一个单线程。
        // 2、调用方法,处理定时任务
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行AAA~~~" + new Date());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 0, 2000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行BB~~~"+ new Date());
//                System.out.println(10/0);
            }
        }, 0, 2000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行CCC~~~"+ new Date());
            }
        }, 0, 3000);
    }
}

2.

2.Timer定时器的使用和了解2

package cn.vqqc.d9_timer;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 目标:Timer定时器的使用和了解
 */
public class TimerDemo2 {
    public static void main(String[] args) {
        // 1、创建ScheduledExecutorService线程池,做定时器
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);

        // 2、开启定时任务
        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:AAA  ==》 " + new Date());
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 0, 2, TimeUnit.SECONDS);


        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:BBB  ==》 " + new Date());
                System.out.println(10 / 0);
            }
        }, 0, 2, TimeUnit.SECONDS);


        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:CCC  ==》 " + new Date());
            }
        }, 0, 2, TimeUnit.SECONDS);

    }
}

视频总结

5.线程同步、同步代码块、同步方法、同步锁

https://www.bilibili.com/video/BV1Cv411372m?p=172

6.线程通信

https://www.bilibili.com/video/BV1Cv411372m?p=173

7.线程池概述、线程池的7个参数详解

https://www.bilibili.com/video/BV1Cv411372m?p=174

8.线程池处理Runnable、 Callable任务

https://www.bilibili.com/video/BV1Cv411372m?p=175

9.Executors的工具类构建线程池对象

https://www.bilibili.com/video/BV1Cv411372m?p=176

10.定时器

https://www.bilibili.com/video/BV1Cv411372m?p=177

11.线程并发、并行、线程生命周期中的6种状态

https://www.bilibili.com/video/BV1Cv411372m?p=178

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容