`
shukuiyan
  • 浏览: 415492 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程同步的一个例子-类似于生产者消费者问题

阅读更多
import java.util.Stack;
/*
 * 多线程同步例子:当厨师线程开始执行put方法或者服务员开始get方法时,都必须先获取MediContainer对象的锁,
 * 如果该锁被其他线程占用,另一个线程就只能在锁池中等待。这种锁机制使得厨师线程执行put方法的整个过程中
 * ,服务员线程不会执行get方法,同样,在服务员线程在执行get方法的整个过程中,厨师线程不执行put方法。
 * 
 * 注意,一个对象的wait方法和notify方法的调用应该放在同步代码块中,并且同步代码块采用这个对象的锁,
   若果违背了这个规则,尽管在编译时不会检查这种错误,但在运行时会跑出IllegalMonitorException异常
 */
public class MutilThreadTest {

	public static void main(String args[]){
		MediContainer med=new MediContainer(5);
		Thread thread[]={
				new Cook(med),
				new Cook(med),
				new Waitress(med),
				new Waitress(med),
				new Waitress(med)
		};
		thread[0].setName("cooker1");
		thread[1].setName("cooker2");
		thread[2].setName("waitress1");
		thread[3].setName("waitress2");
		thread[4].setName("waitress3");
		for(int i=0;i<thread.length;i++){//同时启动两个厨师线程,3个服务员线程
			thread[i].start();
		}
		
		try {
			Thread.sleep(2000);//运行2s后停止运行
			med.setStop(true);
			System.out.println("over");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		for(int i=0;i<thread.length;i++){
			thread[i].stop();
		}
	}
}

class MediContainer{//定义食物存储容器
	public static  Stack<Dish> slot=new Stack<Dish>();
	public int slotCount;
	public boolean stopflag=false;
	public MediContainer(int slotcount){
		this.slotCount=slotcount;
	}
	public void setStop(boolean flag){
		this.stopflag=flag;
	}
	public boolean isStop(){
		return this.stopflag;
	}
	
	public void put(Dish dish){//厨师放菜操作,当slot容器中炒菜数量为最大值时,该容器对象this.wait(),此时调用该方法的线程进入该对象的锁池
		synchronized(this){
			this.notifyAll();
			//唤醒对象等待池中其余的等待线程,即JVM将该对象等待池中的对象都移到锁池中,在这里等待获得锁
			//实际意义是,通知在等待池中的线程(准备从容器中取炒菜的服务员线程)准备到锁池中准备执行
			while(slot.size()==this.slotCount){
				try {
					System.out.println(Thread.currentThread().getName()+"厨师等待放菜....");
					this.wait();//此时,容器已满,厨师放弃对象锁和cpu进入该对象的等待池中
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			slot.push(dish);
			System.out.println(Thread.currentThread().getName()+"完成一个炒菜,此时炒菜数量:"+slot.size());
			
		}
	}
	
	public  Dish get(){
		synchronized(this){
			this.notifyAll();
			//唤醒对象等待池中其余的等待线程,即JVM将该对象等待池中的对象都移到锁池中,在这里等待获得锁;
			//实际意义是,通知在等待池中的线程(准备往容器中放炒菜的厨师线程)准备到锁池中准备执行
			while(slot.size()==0){
				try{
					System.out.println(Thread.currentThread().getName()+"服务员等待端菜....");
					this.wait();
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
			
			System.out.println(Thread.currentThread().getName()+"服务员取走一个炒菜,此时还剩炒菜数量:"+(slot.size()-1));
			return slot.pop();
		}
	}
}

class Cook extends Thread{//定义一个厨师线程
	private int id;
	MediContainer med;
	public static int number=1;
	public Cook(MediContainer med){
		this.id=number++;
		this.med=med;
	}
	
	public void run(){
		while(!med.isStop()){
			Dish dish=new Dish(id);
			med.put(dish);//该方法是同步方法,此时该对象必须获取med对象的同步锁,如果该锁被其他线程占用,则该对象进入med对象的锁池中阻塞
			try {
				Thread.sleep(10);//放弃cpu,将运行机会给别的线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Waitress extends Thread{
	private int id;
	MediContainer med;
	public static int number=1;
	public Waitress(MediContainer med){
		this.id=number++;
		this.med=med;
	}
	public void run(){
		while(!med.isStop()){
			Dish dish=med.get();//该方法是同步方法,此时该对象必须获取med对象的同步锁,如果该锁被其他线程占用,则该对象进入med对象的锁池中阻塞
			try {
				Thread.sleep(200);//放弃cpu,将运行机会给别的线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Dish{
	public int id;
	public Dish(int id){
		this.id=id;
	}
}
 
分享到:
评论

相关推荐

    操作系统课设生产者消费者

    - 类似于生产者消费者问题,是多线程同步的另一个经典例子,有助于理解如何避免死锁。 8. **死锁**: - 当两个或更多线程相互等待对方释放资源,导致无法继续执行的情况称为死锁。 - 避免死锁的方法包括:资源预...

    一个生产者与消费者的例子.

    生产者与消费者问题是一个经典的多线程同步问题,在计算机科学和软件工程中有着广泛的应用。这个问题的核心在于如何在多个线程之间有效地共享有限的资源,确保数据的一致性和避免竞争条件。在这个例子中,我们将深入...

    关于多线程同步的例子

    这是一个类似于消费者生产者的例子 生产者将产生abcd四个命令并将它们写入缓冲区 消费者从缓冲中取出命令 程序采用了 synchronized(this)同步多个线程对缓冲区的访问 具体见程序

    生产者消费者进程 C C++

    在操作系统中,生产者-消费者问题是多线程或进程同步的经典问题,它模拟了两个角色(生产者和消费者)如何在共享资源(如缓冲区)中协作。在这个问题中,生产者生成产品并放入缓冲区,而消费者则从缓冲区取出产品...

    LINUX下的生产者消费者模型算法

    在Linux环境下实现的生产者消费者模型是一种经典的多进程或线程间通信的例子。该模型通过进程模拟生产者与消费者的角色,并利用共享存储区来模拟缓冲区,进而实现了资源的有效管理与分配。 #### 代码解析与知识点...

    java-shengchanzhexiaofeizhe.rar_生产者报告

    总结,生产者消费者问题的解决方案主要依赖于线程同步和通信机制,Java的`BlockingQueue`为此提供了完美的抽象。通过理解和应用这些概念,开发者可以更好地解决并发编程中类似的问题,提高程序的并发性能和稳定性。...

    Qt5多线程同步,QSemaphore类的简单实现

    每个线程中包含一个生产者或消费者逻辑,并通过QSemaphore进行同步。`QThread`类还提供了信号(Signal)和槽(Slot)机制,使得线程间通信变得简单高效。 例如,你可以创建一个Producer类继承自`QObject`,并在其中...

    Java的多线程-线程间的通信.doc

    在Java多线程编程中,线程间的通信是非常重要的概念...例如,在生产者-消费者模型或读者-写者问题中,线程间的通信是解决并发问题的关键。因此,理解并熟练掌握Java中的线程通信机制对于编写高效的多线程程序至关重要。

    cpp代码-生产者,消费者

    标题中的"cpp代码-生产者,消费者"表明这是一个使用C++语言实现的生产者-消费者问题的示例。在C++中,我们可以利用标准模板库(STL)中的队列作为共享数据结构,以及线程库来实现线程间的协作。 描述虽然简短,但...

    实现多线程之间通讯第二节

    这些方法通常用于解决生产者消费者问题、哲学家就餐问题等经典并发问题。 1. **wait() 方法**:当一个线程调用某个对象的`wait()`方法时,它会释放该对象的锁,并进入等待状态。这个线程必须拥有该对象的监视器锁...

    C++多线程同步机制与条件变量的类实例化应用

    其他说明:此示例中采用了最简单的线程同步机制——条件变量与互斥锁相结合的方法,虽然实现了基本的功能但可能不适应所有复杂的应用场景,实际生产环境还需要考虑更多的因素如性能优化、死锁避免等问题。...

    操作系统 缓冲池 C++

    在这个C++实现的例子中,我们看到一个简单的缓冲池模型,其中包含生产者线程(ProducerThread)和消费者线程(ConsumerThread)之间的交互。 首先,代码中定义了一个名为`CQueue`的类,它使用`std::list`容器作为...

    Java线程指南

    生产者/消费者模式是线程协作的经典例子,通过队列作为缓冲区,生产者线程负责生产数据,消费者线程负责消费数据,两者互不影响,但可以通过队列进行通信。Java中可以使用`BlockingQueue`接口实现这一模式。 `Timer...

    java线程讲解

    为了更好地理解Java线程的使用,我们可以考虑一个简单的生产者消费者模型的例子。在这个模型中,有一个缓冲区,生产者不断地向缓冲区中放入产品,而消费者则不断地从中取出产品。通过使用`synchronized`关键字或其他...

    ecos系统同步原语

    - 条件变量允许线程等待特定条件满足后再继续执行,常用于线程间协作,如生产者-消费者模型。线程可以使用`cyg_cond_wait()`等待条件,而其他线程可以通过改变条件并调用`cyg_cond_broadcast()`或`cyg_cond_signal...

    Queue 实现生产者消费者模型(实例讲解)

    总结来说,Python的`Queue`模块提供了一种方便、安全的方式来实现生产者消费者模型,它通过内置的线程同步机制,确保了数据在生产者和消费者之间的正确传递,避免了竞争条件和死锁等问题,提高了程序的稳定性和效率...

    RT-Thread实时操作系统编程指南_0.3.0.

    - **生产者消费者问题:** - 使用生产者消费者模型来演示进程间通信机制,解决资源共享的问题。 #### 四、RT-Thread系统概述 - **实时内核:** - 内核是操作系统的核心部分,负责任务调度、内存管理、中断处理等...

    Java并发编程实践-电子书-05章.pdf

    生产者-消费者模式是一种经典的解决线程间通信问题的设计模式。通过使用阻塞队列(如`java.util.concurrent.BlockingQueue`),可以实现生产者和消费者之间的解耦。 - **阻塞队列**:在队列为空时,`take()`方法会...

    Java基础学习60.pdf

    这是一种典型的多线程协作模型,通过一个缓冲区(如队列)来解耦生产者和消费者线程。生产者将产品放入缓冲区,消费者从缓冲区取出产品。可以使用`synchronized`的`wait()`, `notify()`, `notifyAll()`或者`...

    大并发编程交流

    `ArrayBlockingQueue` 是一种阻塞队列,可以实现生产者消费者模式中的线程同步。 #### 三、并发包中的高级特性 - **AtomicInteger 系列**:这一系列原子类提供了基本类型的原子操作,如 `AtomicInteger`、`...

Global site tag (gtag.js) - Google Analytics