作业:完成生产者消费者模式

一个线程作为消费者,一个线程作为生产者。生产者每生产一次,消费者就消费一次。生产者每次生产的商品数量以及消费者消费的数量使用随机数产生即可。每一次的生产的商品数量和上一次剩余的商品数量之和不能超过1000。

package cn.javasm.demo;
​
​
public class TestDemo {
    public static void main(String[] args) {
​
        Product product = new Product();
​
        new Thread(new Producer(product)).start();
        new Thread(new Producer(product)).start();
        new Thread(new Producer(product)).start();
        new Thread(new Consumer(product)).start();
        new Thread(new Consumer(product)).start();
        new Thread(new Consumer(product)).start();
    }
}
​
class Consumer implements Runnable{
​
    private Product product;
​
    public Consumer(Product product) {
        this.product = product;
    }
​
    @Override
    public void run() {
        while (true){
            synchronized (product){
                while (product.flag){
                    try {
                        product.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 计算本次所消费的商品数量
                int count = (int)(Math.random() * (product.getCount() + 1));
                // 计算本次剩余的商品数量
                product.setCount(product.getCount() - count);
​
                System.out.println("本次消费的商品数量为:" + count + ",本次剩余的商品数量为" + product.getCount());
​
                product.flag = true;
                // 唤醒所有的线程
                product.notifyAll();
            }
        }
    }
}
​
/**
 * 生产者
 */
class Producer implements Runnable{
​
    private Product product;
​
    public Producer(Product product) {
        this.product = product;
    }
​
    @Override
    public void run() {
        while (true){
            synchronized (product) {
                while (!product.flag){
                    try {
                        product.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
​
                // 计算本次所能生产的最大数量
                int max = 1000 - product.getCount();
                // 计算本次生产的实际数量
                int count = (int)(Math.random() * (max + 1));
                // 计算本次所能提供的商品数量
                product.setCount(product.getCount() + count);
​
                System.out.println("本次生产的商品数量为:" + count + ",本次提供的商品数量为:" + product.getCount());
​
                product.flag = false;
                // 唤醒所有的线程
                product.notifyAll();
            }
        }
    }
}
​
/**
 * 商品
 */
class Product{
    /**
     * 数量
     */
    private int count;
    /**
     * 规定true表示生产,false表示消费
     */
    public boolean flag = true;
​
    public int getCount() {
        return count;
    }
​
    public void setCount(int count) {
        this.count = count;
    }
}
​

6 线程池

6.1 Executors

package cn.javasm.demo;
​
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
​
public class TestDemo4 {
    public static void main(String[] args) {
        demo4();
    }
​
    private static void demo4() {
        // 创建可以执行延时的线程池
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        // 延迟5秒执行异步任务
        scheduledExecutorService.schedule(()-> System.out.println("hello world" + LocalDateTime.now()),5, TimeUnit.SECONDS);
    }
​
    private static void demo3() {
        // 创建一个可以伸缩的线程池对象
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 1000; i++) {
            executorService.submit(()-> System.out.println(Thread.currentThread().getName() + "执行了..."));
        }
    }
​
    private static void demo2() {
        // 创建固定数量线程对象的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 20; i++) {
            executorService.execute(()-> System.out.println(Thread.currentThread().getName() + "执行了..."));
        }
​
    }
​
    private static void demo1() {
        // 创建只有1个线程实例的线程池
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            executorService.submit(()-> System.out.println(Thread.currentThread().getName() + "执行了。。。"));
        }
        // 关闭线程池  等待任务全部完成之后才会关闭
        executorService.shutdown();
        // 立即关闭线程池
//        executorService.shutdownNow();
    }
}
​

6.2 ThreadPoolExecutor

private static void demo5() {
        // corePoolSize:核心线程数量
        // maximumPoolSize:最大线程数量
        // keepAliveTime:在指定的时间内回收不用的线程  (线程活跃时间)
        // unit: 时间单位
        // workQueue:工作队列  如果异步任务超过100个,需要排队等待
        //          ArrayBlockingQueue:  有界队列
        //          LinkedBlockingQueue: 无界队列
        //          PriorityBlockingQueue:优先级队列
        // ThreadFactory threadFactory: 创建线程对象
        // RejectedExecutionHandler handler: 拒绝策略   去主线程执行
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,100,5,TimeUnit.MINUTES,new ArrayBlockingQueue<>(100),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolExecutor.execute(()-> System.out.println("helloworld"));
    }

在项目下创建data.properties文件

corePoolSize=5
maxPoolSize=100
keepAliveTime=5
capacity=100

package cn.javasm.util;
​
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.*;
​
public class MyThreadPool {
​
    // 饿汉式
​
    private MyThreadPool(){}
​
    private static final MyThreadPool MY_THREAD_POOL = new MyThreadPool();
​
    private static final ThreadPoolExecutor POOL_EXECUTOR;
​
    private static final ScheduledThreadPoolExecutor SCHEDULED_THREAD_POOL_EXECUTOR;
​
    static {
        // 加载data.properties文件
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("data.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        POOL_EXECUTOR = new ThreadPoolExecutor(Integer.parseInt(properties.getProperty("corePoolSize")),Integer.parseInt(properties.getProperty("maxPoolSize")),Integer.parseInt(properties.getProperty("keepAliveTime")), TimeUnit.MINUTES,new ArrayBlockingQueue<>(Integer.parseInt(properties.getProperty("capacity"))), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());
        SCHEDULED_THREAD_POOL_EXECUTOR = new ScheduledThreadPoolExecutor(Integer.parseInt(properties.getProperty("corePoolSize")),Executors.defaultThreadFactory());
    }
​
​
    public static MyThreadPool getInstance(){
        return MY_THREAD_POOL;
    }
    // 执行异步任务
    public void task(Runnable runnable){
        POOL_EXECUTOR.submit(runnable);
    }
    // 延迟time时间执行
    public void delayTask(Runnable runnable,long time,TimeUnit unit){
        SCHEDULED_THREAD_POOL_EXECUTOR.schedule(runnable,time,unit);
    }
​
    public void release(){
        POOL_EXECUTOR.shutdown();
    }
​
    public void releaseNow(){
        POOL_EXECUTOR.shutdownNow();
    }
​
​
}
​

7 单例模式

保证对应类产生的对象在整个项目中只有一个,这种就是单例设计模式

package cn.javasm.demo;
​
public class TestDemo6 {
    public static void main(String[] args) {
//        TaskMgr instance = TaskMgr.getInstance();
//        System.out.println(instance);
//
//        TaskMgr instance1 = TaskMgr.getInstance();
//        System.out.println(instance1);
        TaskMgr.m();
​
​
    }
}
​
// 懒汉式
class TaskMgr{
​
    private TaskMgr(){
        System.out.println("构造方法执行了");
    }
​
    private static TaskMgr taskMgr;
​
    public static TaskMgr getInstance(){
        // 懒加载 lazyload
        if (taskMgr == null)
            taskMgr = new TaskMgr();
        return taskMgr;
    }
​
    public static void m(){
        System.out.println("m......");
    }
}
​
// 饿汉式
class TaskManager{
​
    // 私有的构造方法,防止外部随意创建对象
    private TaskManager(){
        System.out.println("私有的构造方法");
    }
​
    private static TaskManager taskManager = new TaskManager();
​
    public static TaskManager getInstance(){
        return taskManager;
    }
​
    public static void m(){
        System.out.println("m.....");
    }
}

懒汉式:对象是在真正使用的时候才进行初始化,节省加载时间。线程不安全

饿汉式:只要使用到了类,就是创建对应的对象,降低了加载效率。线程安全

8 线程的优先级

线程的优先级分为1-10,理论上数字越大优先级越高,抢占到资源的概率就越大。

相邻的优先级之间的差别实际上非常不明显。

public static void main(String[] args) {
        // 默认优先级
        System.out.println(Thread.NORM_PRIORITY);
        // 最小优先级
        System.out.println(Thread.MIN_PRIORITY);
        // 最大优先级
        System.out.println(Thread.MAX_PRIORITY);
​
        Thread thread1 = new Thread(()->{
            for (int i = 0; i < 1000; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        },"线程1");
​
        Thread thread2 = new Thread(()->{
            for (int i = 0; i < 1000; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        },"线程2");
​
        // 设置优先级
        thread1.setPriority(1);
        thread2.setPriority(10);
​
        thread1.start();
        thread2.start();
    }

9 守护线程

如果一个线程不是守护线程,那么就是被守护线程。如果所有的被守护线程结束,那么守护线程才会随之结束。

ZGC就是一个守护线程。

public static void main(String[] args) {
        Thread thread1 = new Thread(new Solider(),"小兵1");
        Thread thread2 = new Thread(new Solider(),"小兵2");
        Thread thread3 = new Thread(new Solider(),"小兵3");
​
        // 设置成守护线程
        thread1.setDaemon(true);
        thread2.setDaemon(true);
        thread3.setDaemon(true);
​
        thread1.start();
        thread2.start();
        thread3.start();
​
        for (int i = 10; i >= 0; i--) {
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
​
            System.out.println("Boos还有" + i + "滴血");
        }
    }

10 线程的状态

public enum State {
        /**
         * 新建还没有执行的线程
         */
        NEW,
​
        /**
         * 正在运行的线程
         */
        RUNNABLE,
​
        /**
         * 阻塞状态
         */
        BLOCKED,
​
        /**
         * 等待状态  需要其他线程手动唤醒
         */
        WAITING,
​
        /**
         * 等待一段时间
         */
        TIMED_WAITING,
​
        /**
         * 结束 停止状态
         */
        TERMINATED;
    }

总结:wait和sleep有什么区别?

sleep需要指定休眠时间,到点自然醒。如果线程没有锁,那么会释放执行权,如果线程有锁,那么不释放执行权。这个方法是设计在Thread类上的,是一个静态方法

wait可以指定也可以不指定,如果不指定时间需要进行唤醒。释放锁,释放执行权。这个方法是设计在Object上的方法,是一个对象方法

JDK17部分特性

1 Record

// Rocord本质上就是一个类,定义不可变的记录数据类
// 会自动提供全参构造,toString方法,getter方法,equals和hashCode方法
// ()中的属性会自动添加private final修饰符
// Record类是一个最终类,不能被继承
// Record只能声明静态变量
public record Student(String studentName,String password) {
    
    public static int age;
    
    public void eat(){
        
    }
}

2 密封类

  • 密封类使用sealed关键字进行声明,必须要有子类

  • 密封类的子类必须被final,sealed,或者non-sealed修饰

  • 使用permits关键字,指定允许继承的子类

// 代表职业的类
sealed class Proffession permits Actor,Teacher,Doctor{
​
}
​
//class Dog extends Proffession{}
​
sealed class Actor extends Proffession{
    
}
final class A extends Actor{
    
}
​
non-sealed class Teacher extends Proffession{
​
}
​
final class Doctor extends Proffession{
    
}

定义一个代表形状的接口,指定实现类矩形圆形和正方形,并且提供求周长和面积的方法

sealed interface Shape permits Rectangle,Circle{
    // 获取周长
    double getGirth();
    
    // 获取面积
    double getArea();
}
​
non-sealed class Circle implements Shape{
    
    private double radius;
​
    public Circle(double radius) {
        this.radius = radius;
    }
​
    @Override
    public double getGirth() {
        return 2 * Math.PI * radius;
    }
​
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}
​
sealed class Rectangle implements Shape permits Square{
    
    private double length;
    
    private double width;
​
    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
​
    @Override
    public double getGirth() {
        return 2 * (width + length);
    }
​
    @Override
    public double getArea() {
        return length * width;
    }
}
​
final class Square extends Rectangle{
​
    public Square(double length) {
        super(length, length);
    }
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐