Producer-Consumer--生产者消费者

本文介绍了生产者消费者模式,通过实例展示了如何运作。生产者将数据生产后交由消费者处理,文章探讨了模式的角色,包括Data、Producer、Consumer和Channel。同时,文章提到了可取消的繁重工作场景,以及notify和notifyAll在多线程中的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义:

Producer-Consumer--生产者消费者模式:生产者将数据交给消费者。

引例:

类的一览表
名字说明

main

测试行为类
makethread厨师类
eaterthread客人类
table桌子类

 

/* *
 * ProducerConsumer中的角色
 * 1.producer
 * 2.consumer
 * 3.channel
 * 4.data
 * 线程的协调运行考虑“放在中间的东西”
 * 线程互斥考虑“应该保护的东西”
 * */
public class Main {
	public static void main(String[] args) {
		Table table = new Table(3); // 建立可以放置3個蛋糕的桌子
		new MakerThread("MakerThread-1", table, 31415).start();
		new MakerThread("MakerThread-2", table, 92653).start();
		new MakerThread("MakerThread-3", table, 58979).start();
		new EaterThread("EaterThread-1", table, 32384).start();
		new EaterThread("EaterThread-2", table, 62643).start();
		new EaterThread("EaterThread-3", table, 38327).start();
	}
}
//管道
public class Table {
	private final String[] buffer;
	private int tail; // 下一个放put的地方
	private int head; // 下一个放的take地方 よ
	private int count; // buffer内的蛋糕数

	public Table(int count) {
		this.buffer = new String[count];
		this.head = 0;
		this.tail = 0;
		this.count = 0;
	}

	// 放置蛋糕
	public synchronized void put(String cake) throws InterruptedException {
		System.out.println(Thread.currentThread().getName() + " puts " + cake);
		while (count >= buffer.length) {
			wait();
		}
		buffer[tail] = cake;
		tail = (tail + 1) % buffer.length;
		count++;
		notifyAll();
	}

	// 取得蛋糕
	public synchronized String take() throws InterruptedException {
		while (count <= 0) {
			wait();
		}
		String cake = buffer[head];
		head = (head + 1) % buffer.length;
		count--;
		notifyAll();
		System.out.println(Thread.currentThread().getName() + " takes " + cake);
		return cake;
	}
}

 

//生产者
public class MakerThread extends Thread {
	private final Random random;
	private final Table table;
	private static int id = 0; // 蛋糕的流水号(所有厨师共通)

	public MakerThread(String name, Table table, long seed) {
		super(name);
		this.table = table;
		this.random = new Random(seed);
	}

	public void run() {
		try {
			while (true) {
				Thread.sleep(random.nextInt(1000));
				String cake = "[ Cake No." + nextId() + " by " + getName() + " ]";
				table.put(cake);
			}
		} catch (InterruptedException e) {
		}
	}

	private static synchronized int nextId() {
		return id++;
	}
}
//消费者
public class EaterThread extends Thread {
	private final Random random;
	private final Table table;

	public EaterThread(String name, Table table, long seed) {
		super(name);
		this.table = table;
		this.random = new Random(seed);
	}

	public void run() {
		try {
			while (true) {
				String cake = table.take();
				Thread.sleep(random.nextInt(1000));
			}
		} catch (InterruptedException e) {
		}
	}
}

结果: 

MakerThread-2 puts [ Cake No.0 by MakerThread-2 ]
EaterThread-3 takes [ Cake No.0 by MakerThread-2 ]
MakerThread-1 puts [ Cake No.1 by MakerThread-1 ]
EaterThread-2 takes [ Cake No.1 by MakerThread-1 ]
MakerThread-3 puts [ Cake No.2 by MakerThread-3 ]
EaterThread-1 takes [ Cake No.2 by MakerThread-3 ]
MakerThread-2 puts [ Cake No.3 by MakerThread-2 ]
EaterThread-3 takes [ Cake No.3 by MakerThread-2 ]
MakerThread-3 puts [ Cake No.4 by MakerThread-3 ]

 Producer-Consumer--生产者消费者模式角色

Data类:由producer生产,供consumer使用。

Producer类:生产Data,并传递给Channel角色

Consumer类:从Channel角色取得Data,并使用

Channel类:Channel角色充当Producer角色和Consumer角色的中间者。

可以取消的繁重工作

我们先看这么一个代码,在这里有一个繁重的工作。请修改Host使得任务可以取消

public class Host {
    public static void execute(int count) throws InterruptedException {
        for (int i = 0; i < count; i++) {
            doHeavyJob();
        }
    }
    private static void doHeavyJob() {       
        System.out.println("doHeavyJob BEGIN");
        long start = System.currentTimeMillis();
        while (start + 10000 > System.currentTimeMillis()) {
            // busy loop
        }
        System.out.println("doHeavyJob END");
    }
}

这样修改:是不是还简单!!

public class Host {
	public static void execute(int count) throws InterruptedException {
		for (int i = 0; i < count; i++) {
			if (Thread.interrupted()) {
				throw new InterruptedException();
			}
			doHeavyJob();
		}
	}

	private static void doHeavyJob() {
		// 繁重的工作
		System.out.println("doHeavyJob BEGIN");
		long start = System.currentTimeMillis();
		while (start + 10000 > System.currentTimeMillis()) {
			// busy loop
		}
		System.out.println("doHeavyJob END");
	}
}
public class Main {
    public static void main(String[] args) {
        Thread executor = new Thread() {
            public void run() {
                System.out.println("Host.execute BEGIN");
                try {
                    Host.execute(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Host.execute END");
            }
        };
        executor.start();
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
        }
        System.out.println("***** interrupt *****");
        executor.interrupt();
    }
}

notitf与notitfall的案例lazythread

public class LazyThread extends Thread {
    private final Table table;
    public LazyThread(String name, Table table) {
        super(name);
        this.table = table;
    }
    public void run() {
        while (true) {
            try {
                synchronized (table) {
                    table.wait();
                }
                System.out.println(getName() + " is notified!");
            } catch (InterruptedException e) {
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Table table = new Table(3);   
        new MakerThread("MakerThread-1", table, 31415).start();
        new MakerThread("MakerThread-2", table, 92653).start();
        new MakerThread("MakerThread-3", table, 58979).start();
        new EaterThread("EaterThread-1", table, 32384).start();
        new EaterThread("EaterThread-2", table, 62643).start();
        new EaterThread("EaterThread-3", table, 38327).start();
        new LazyThread("LazyThread-1", table).start();
        new LazyThread("LazyThread-2", table).start();
        new LazyThread("LazyThread-3", table).start();
        new LazyThread("LazyThread-4", table).start();
        new LazyThread("LazyThread-5", table).start();
        new LazyThread("LazyThread-6", table).start();
        new LazyThread("LazyThread-7", table).start();
    }
}

结论:notify只能唤醒正在等待队列中的一个线程,notifyall是全部。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值