今天的db2培训仍然没有太多的实践,围绕考试来的,闲着也是闲着,想到我们后续业务中使用多线程的地方比较多。于是想起那个经典的案例:生产者和消费者
关于这个案例的原理,就不多说了。主要涉及到临界资源互斥锁的使用、wait和notify操作,还有就是线程sleep。关于几个操作的区别,我会写在代码的注释中。这和我的工作习惯有关系,不喜欢写文档(敏捷开发认为代码是最好的文档,^_^,我的代码没有重构,完成了功能就贴上来了,当然不符合敏捷的要求了^_^,见谅)
请看代码:
1、生产和消费的产品抽象类
//预留 public abstract class Product { public String name; public abstract String toString(); }
2、一个具体的产品类
public class AProduct extends Product { public AProduct(String pname) { super(); name = pname; // TODO Auto-generated constructor stub } public String toString() { // TODO Auto-generated method stub return name; } }
3、容器类(仓库)
import java.util.ArrayList; /* * 存放生产者和消费者的产品队列 * */ public class Container { private ArrayList arrList = new ArrayList(); private int LENGTH = 10; public boolean isFull() { return arrList.size() == LENGTH; } public boolean isEmpty() { return arrList.isEmpty(); } /* 如果此处不加synchronized锁,那么也可以再调用push的地方加锁 * 既然此处加了锁,那么再别的地方可以不加锁 */ public synchronized void push(Object o) { arrList.add(o); } // 如果此处不加synchronized锁,那么也可以再调用push的地方加锁 public synchronized Object pop() { Object lastOne = arrList.get(arrList.size() - 1); arrList.remove(arrList.size() - 1); return lastOne; } }
4、休息一会,生产者和消费者都要休息,因此作为抽象基类
public abstract class Sleep { public void haveASleep() throws InterruptedException { Thread.sleep((long) (Math.random() * 3000)); } }
// sleep让出cpu时间给其他线程执行.也许你会问,既然我已经wait了,为什么还要sleep? // wait()的作用就是阻塞当前线程并且释放对象的锁给别人(一般是等待队列中的第一个线程) // Thead.sleep()也是阻塞当前线程,但不释放锁。 // sleep()方法是使线程停止一段时间的方法。 // 在sleep 时间间隔期满后,线程不一定立即恢复执行。 // 这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非 (a)“醒来”的线程具有更高的优先级。 // (b)正在运行的线程因为其它原因而阻塞。 wait()是线程交互时,如果线程对一个同步对象x // 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。 // 当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。 // waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized
/* * 消费者线程 **/ public class Consumer extends Sleep implements Runnable { private Container contain = null; public Consumer(Container contain) { super(); this.contain = contain; } public void run() { // TODO Auto-generated method stub while (true) { synchronized (contain) { while (contain.isEmpty()) { try { contain.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } consume();//消费 try { haveASleep(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (contain) { contain.notify(); } } } private void consume() { Product a = (AProduct) contain.pop(); System.out.println("消费了一个产品" + a.toString()); } }
/* * 生产者线程 * */ public class Producator extends Sleep implements Runnable { private Container contain = null; public Producator(Container contain) { super(); this.contain = contain; } public void run() { // TODO Auto-generated method stub while (true) { synchronized (contain) { while (contain.isFull()) { try { contain.wait();// 阻塞当前线程,当前线程进入等待队列。这个时候只有等待别的线程来唤醒自己了。 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } producer();// 生产一个产品 try { haveASleep(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (contain) { contain.notify();// 唤醒等待队列中正在等待的第一个线程,让其执行。 } } } public void producer() { Product aProduct = new AProduct("pp:" + String.valueOf(Math.random())); System.out.println("生产了一个产品:" + aProduct.toString()); contain.push(aProduct); } }
5、写一个测试吧:
public class TestMain { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Container contain = new Container(); Producator p = new Producator(contain); Consumer c = new Consumer(contain); Thread pt = new Thread(p); Thread ct = new Thread(c); pt.start(); ct.start(); } }
好了,看看执行结果吧:
生产了一个产品:pp:0.5010546528255287
生产了一个产品:pp:0.08173509855014827
消费了一个产品pp:0.5010546528255287
生产了一个产品:pp:0.7022996270428004
相关推荐
操作系统课程设计报告——生产者与消费者算法的实现 在计算机科学中,生产者与消费者问题是一个经典的多线程同步问题,常被用于演示如何在并发环境中有效地管理共享资源。这个问题的核心在于平衡生产者(生成数据的...
在操作系统领域,生产者消费者问题是多线程编程中一个经典的同步问题,而先来先服务(First-Come, First-Served, FCFS)算法是调度策略的一种,它们都是理解并发控制和资源管理的重要概念。 生产者消费者问题描述的...
生产者消费者问题其主要实现就是模拟进程之间的同步与互斥。 读者写者问题是在生产者消费者问题的基础上改进而来,其不同点仅在于加入一个计数变量count来记录处于读写空间中读者的数量,实现读者可同时读文件。 ...
"操作系统生产者与消费者Java源代码详解" 操作系统生产者与消费者是一个经典的计算机科学问题,旨在解决多个进程之间的同步问题。在Java语言中,可以使用多种方法实现生产者与消费者模型。本文将通过Java图形用户...
### Java生产者消费者问题知识点详解 #### 一、实验背景及意义 生产者-消费者问题是计算机科学中的一个经典问题,通常用于演示并发编程中的同步机制。这个问题涉及到如何在多个线程之间分配有限资源的问题,是多...
生产者消费者算法是一种在多线程编程中广泛使用的同步机制,它源于计算机科学中的经典问题,用于解决资源的共享和分配。在这个问题中,生产者线程负责生成数据,而消费者线程则负责消费这些数据。为了确保生产者不会...
在Java编程中,死锁和生产者消费者问题是多线程编程中的两个重要概念,它们涉及到并发执行和资源管理。理解并正确处理这些问题对于构建高效、可靠的多线程应用至关重要。 死锁是指两个或多个线程在执行过程中,因...
在这个实验中,主要目标是通过Java编程实现基于信号量机制的进程(线程)同步和互斥,以模拟生产者和消费者如何共享有限的缓冲区资源。 1. **实验环境**: - 课程:操作系统 - 学生信息:未提供具体信息 - 实验...
本次课程设计选到的题目为生产者消费者算法模拟,通过需求分析和资料搜寻,掌握到生产者/消费者的模式原理和优点,同时也了解到了几种可以实现生产者消费者的方式,如信号量方式,管程方式,阻塞队列方式等。
生产者与消费者算法模拟课程设计 本课程设计的主要目标是设计并实现一个生产者与消费者算法模拟系统,通过该系统来模拟生产者和消费者之间的资源分配和竞争关系。系统将模拟多个生产者和消费者之间的交互,根据系统...
JAVA多线程实现生产者消费者的实例详解 JAVA多线程实现生产者消费者是指在JAVA编程语言中使用多线程技术来实现生产者消费者模型的实例详解。生产者消费者模型是指在计算机科学中的一种经典模式,描述了生产者和消费...
解决生产者-消费者问题的记录型信号量方法 在计算机科学中,生产者-消费者问题是一个经典的同步问题,描述了多个进程之间的协作和资源竞争。在这里,我们将讨论使用记录型信号量解决生产者-消费者问题的方法。 ...
5. 生产者-消费者模型:这是一个经典的多线程问题,使用队列作为共享资源,生产者负责往队列里添加元素,消费者则负责取出并处理元素。 Java 中的数据结构和算法是程序员必备的技能,理解并熟练运用图算法和队列...
总结来说,这个Java程序通过使用信号量和多线程技术,生动地演示了解决"生产者-消费者"问题的过程。它不仅展示了如何在Java中实现线程同步,还通过图形界面和随机休眠策略来模拟现实生活中的并发挑战,这对于理解和...
在广工的操作系统实现报告中,主要涵盖了四个关键领域的实践:银行家算法、动态内存分配、生产者消费者问题以及进程调度。这些都是操作系统理论与实践的重要组成部分。 1. **银行家算法**:这是解决资源分配安全性...
生产消费者问题是操作系统设计中经常遇到的问题。多个生产者和消费者线程访问在共享内存中的环形缓冲。生产者生产产品并将它放入环形缓冲,同时消费者从缓冲中取出产品并消费。当缓冲区满时生产者阻塞并且当缓冲区...
### C++ PV操作(生产者/消费者)简单实例解析 #### 概述 在多线程编程中,生产者-消费者问题是一个经典的同步问题。它描述了一组生产数据的线程(生产者)和一组消费这些数据的线程(消费者)。为了确保线程间的...
Java网络编程中的“生产者-消费者问题”是一个经典的多线程同步问题,它涉及到进程间的协作与通信。在这个实验中,我们看到一个简单的实现,包括两个生产者和一个消费者,以及一个最大容量为两个产品的仓库。 1. **...
Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解 该篇文章主要介绍了Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解,通过对生产者消费者模式的编程实现和等待唤醒机制的应用,阐述了多...