Java线程(三):线程协作-生产者/消费者模式
来源:互联网 发布:centos 360wifi 编辑:程序博客网 时间:2024/06/06 03:01
上一篇讲述了线程的互斥(同步),但是在很多情况下,仅仅同步是不够的,还需要线程与线程协作(通信),生产者/消费者模式是一个经典的线程同步以及通信的模型。
假设有这样一种情况,有一个盘子,盘子里只能放一个鸡蛋,A线程专门往盘子里放鸡蛋,如果盘子里有鸡蛋,则一直等到盘子里没鸡蛋,B线程专门从盘子里取鸡蛋,如果盘子里没鸡蛋,则一直等到盘子里有鸡蛋。这里盘子是一个互斥区,每次放鸡蛋是互斥的,每次取鸡蛋也是互斥的,A线程放鸡蛋,如果这时B线程要取鸡蛋,由于A没有释放锁,B线程处于等待状态,进入阻塞队列,放鸡蛋之后,要通知B线程取鸡蛋,B线程进入就绪队列,反过来,B线程取鸡蛋,如果A线程要放鸡蛋,由于B线程没有释放锁,A线程处于等待状态,进入阻塞队列,取鸡蛋之后,要通知A线程放鸡蛋,A线程进入就绪队列。我们希望当盘子里有鸡蛋时,A线程阻塞,B线程就绪,盘子里没鸡蛋时,A线程就绪,B线程阻塞,代码如下:
- import java.util.ArrayList;
- import java.util.List;
- /** 定义一个盘子类,可以放鸡蛋和取鸡蛋 */
- public class Plate {
- /** 装鸡蛋的盘子 */
- List<Object> eggs = new ArrayList<Object>();
- /** 取鸡蛋 */
- public synchronized Object getEgg() {
- while (eggs.size() == 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Object egg = eggs.get(0);
- eggs.clear();// 清空盘子
- notify();// 唤醒阻塞队列的某线程到就绪队列
- System.out.println("拿到鸡蛋");
- return egg;
- }
- /** 放鸡蛋 */
- public synchronized void putEgg(Object egg) {
- while (eggs.size() > 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- eggs.add(egg);// 往盘子里放鸡蛋
- notify();// 唤醒阻塞队列的某线程到就绪队列
- System.out.println("放入鸡蛋");
- }
- static class AddThread extends Thread {
- private Plate plate;
- private Object egg = new Object();
- public AddThread(Plate plate) {
- this.plate = plate;
- }
- public void run() {
- plate.putEgg(egg);
- }
- }
- static class GetThread extends Thread {
- private Plate plate;
- public GetThread(Plate plate) {
- this.plate = plate;
- }
- public void run() {
- plate.getEgg();
- }
- }
- public static void main(String args[]) {
- Plate plate = new Plate();
- for(int i = 0; i < 10; i++) {
- new Thread(new AddThread(plate)).start();
- new Thread(new GetThread(plate)).start();
- }
- }
- }
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
- 放入鸡蛋
- 拿到鸡蛋
前段时间看了张孝祥老师线程的视频,讲述了一个其学员的面试题,也是线程通信的,在此也分享一下。
题目:子线程循环10次,主线程循环100次,如此循环100次,好像是空中网的笔试题。
- public class ThreadTest2 {
- public static void main(String[] args) {
- final Business business = new Business();
- new Thread(new Runnable() {
- @Override
- public void run() {
- threadExecute(business, "sub");
- }
- }).start();
- threadExecute(business, "main");
- }
- public static void threadExecute(Business business, String threadType) {
- for(int i = 0; i < 100; i++) {
- try {
- if("main".equals(threadType)) {
- business.main(i);
- } else {
- business.sub(i);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class Business {
- private boolean bool = true;
- public synchronized void main(int loop) throws InterruptedException {
- while(bool) {
- this.wait();
- }
- for(int i = 0; i < 100; i++) {
- System.out.println("main thread seq of " + i + ", loop of " + loop);
- }
- bool = true;
- this.notify();
- }
- public synchronized void sub(int loop) throws InterruptedException {
- while(!bool) {
- this.wait();
- }
- for(int i = 0; i < 10; i++) {
- System.out.println("sub thread seq of " + i + ", loop of " + loop);
- }
- bool = false;
- this.notify();
- }
- }
- Java线程(三):线程协作-生产者/消费者模式
- Java线程(三):线程协作-生产者/消费者模式
- Java线程(三):线程协作-生产者/消费者模式
- Java线程(三):线程协作-生产者/消费者模式
- 线程协作-生产者/消费者模式
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- 黑马程序员——自学笔记14(网络编程1—概念和过程)
- 享受寂寞
- Java线程(二):线程同步synchronized和volatile
- 黑马程序员_java基础加强—HTML&CSS
- 伤秋
- Java线程(三):线程协作-生产者/消费者模式
- 更改Myeclipse的Workspace
- Java线程(四):Timer和TimerTask
- 明年的七夕,你还记得我吗
- Kconfig和Makefile的作用
- iOS6 新的可用于device id的方案
- CSDN高校俱乐部网站改版公告
- 数据储存之文件操作
- Android 饼图