wait和notify实现消费者和生产者

577 阅读1分钟

使用Thread中的wait()和notify()方法实现生产消费者关系:

项目类:

image.png

效果:

image.png

解释说明: image.png

下面给出的代码中,有很多可以优化的地方,有其他的见解可以在下面给点评论

源代码一:

import dream.on.sakura.container.ThreadContainer;
import dream.on.sakura.container.Ticket;
import dream.on.sakura.customer.Customer;
import dream.on.sakura.producer.Producer;

import java.util.Date;
import java.util.LinkedList;

/**
 * @ClassName TestMain
 * @function [业务功能]
 * @Author lcz
 * @Date 2021/07/11 07:50
 */
public class TestMain {
    public static void main(String[] args) {

        ThreadContainer<Ticket> ticketThreadContainer = new ThreadContainer<>(2, 5, new LinkedList<>());

        Date time = new Date();
        Producer producer = new Producer(ticketThreadContainer, time);
        Customer customer = new Customer(ticketThreadContainer);
        new Thread(producer).start();
        new Thread(customer).start();
    }
}


import java.util.Date;
import java.util.LinkedList;

/**
 * @ClassName ThreadContainer
 * @function [消费者和生产者资源存储容器]
 * @Author lcz
 * @Date 2021/07/11 07:13
 */
public class ThreadContainer<T> {
    // 资源池允许的最小值
    private volatile int minSize;
    // 资源池允许的最大值
    private volatile int maxSize;
    // 数据资源存储对象
    private LinkedList<T> linkedList;

    // 构造器初始化参数限制
    public ThreadContainer(int minSize, int maxSize, LinkedList<T> linkedList){
        this.minSize = minSize;
        this.maxSize = maxSize;
        this.linkedList = linkedList;
    }

    // 生产者生产方法,线程安全
    public synchronized void produce(T data) throws InterruptedException {
        while (maxSize == linkedList.size()) {
            wait();
        }
        linkedList.add(data);
        System.out.println(">>>>>>>>>> 生产时间:" + new Date() + ", 生产内容:" + data.toString() + ", 资源容器中资源数量" + linkedList.size());
        notify();
    }

    // 消费者消费方法,线程安全
    public synchronized T custom() throws InterruptedException {
        while (minSize >= linkedList.size()) {
            wait();
        }
        T t = linkedList.poll();
        System.out.println("<<<<<<<<<< 消费时间:" + new Date() + ", 消费内容:" + t.toString() + ", 资源容器中资源数量" + linkedList.size());
        notify();
        return t;
    }
}




import java.util.Date;

/**
 * @ClassName Ticket
 * @function [生产-消费的对象]
 * @Author lcz
 * @Date 2021/07/11 07:39
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Ticket {
    private String station;
    private String destination;
    private Date time;

    @Override
    public String toString() { return "票根:【始发站: " + station + "----> 终点: '" + destination + ", 出发时间:" + time + '】'; }
}


import dream.on.sakura.container.Ticket;
import dream.on.sakura.container.ThreadContainer;

import java.util.Random;

/**
 * @ClassName Customer
 * @function [业务功能]
 * @Author lcz
 * @Date 2021/07/11 07:35
 */
public class Customer implements Runnable {
    private ThreadContainer<Ticket> threadContainer;

    public Customer(ThreadContainer<Ticket> threadContainer) {
        this.threadContainer = threadContainer;
    }

    @Override
    public void run() {
        for (;;) {
            try {
                Ticket custom = threadContainer.custom();
                Thread.sleep(new Random().nextInt(2000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}



import dream.on.sakura.container.Ticket;
import dream.on.sakura.container.ThreadContainer;
import org.apache.commons.lang3.time.DateUtils;

import java.util.Date;
import java.util.Random;

/**
 * @ClassName Producer
 * @function [业务功能]
 * @Author lcz
 * @Date 2021/07/11 07:35
 */
public class Producer implements Runnable{
    private ThreadContainer<Ticket> threadContainer;

    private Date time;

    public Producer(ThreadContainer<Ticket> threadContainer, Date time) {
        this.threadContainer = threadContainer;
        this.time = time;
    }

    @Override
    public void run() {
        for (;;) {
            Ticket ticket = new Ticket("南京", "亳州", DateUtils.addDays(time, 1));
            try {
                threadContainer.produce(ticket);
                Thread.sleep(new Random().nextInt(2000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}