要求:用两个线程模拟存票、售票过程。但要求每存入一张票,就售出一张票,售出后,再存入,直到售完为止。

用到的知识点:线程等待、唤醒、可能的线程中断异常

下面的方式一和方式二采用的是唤醒所有等待的线程,即wait()和notify()方法

方式一:继承Thread

class Tickets //定义(资源)票类
{
protected int size;//总票数
int number=0; //票号
Boolean available=false;//表示当前是否有票可售
public Tickets(int size)
{
this.size = size;
}
public synchronized void store() //同步方法,实现存票功能
{
if(available) //如果线程还有票可售,则存票线程等待
try{wait();}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
available = true;
notify(); //存票后,唤醒售票线程开始售票
} public synchronized void sale() //同步方法,实现售票功能
{
if(!available) //如果线程没有票可售,则售票线程等待
try{wait();}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
available = false;
notify(); //售票后,唤醒存票线程开始存票
}
} class Productor extends Thread //定义生产者(存票)线程类
{
private Tickets t;
public Productor(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<t.size)
t.store();
else
System.exit(0);
}
}
} class Costomer extends Thread //定义消费者(售票)线程类
{
private Tickets t;
public Costomer(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<=t.size)
t.sale();
else
System.exit(0);
}
}
}
class TicketStoreSale3
{
public static void main(String[] args)
{
Tickets t = new Tickets(10); Productor t1 = new Productor(t);
Costomer t2 = new Costomer(t); t1.start();
t2.start();
}
}

方式二:实现Runnable接口

class Tickets //定义(资源)票类
{
protected int size;//总票数
int number=0; //票号
Boolean available=false;//表示当前是否有票可售
public Tickets(int size)
{
this.size = size;
}
public synchronized void store() //同步方法,实现存票功能
{
if(available) //如果线程还有票可售,则存票线程等待
try{wait();}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
available = true;
notify(); //存票后,唤醒售票线程开始售票
} public synchronized void sale() //同步方法,实现售票功能
{
if(!available) //如果线程没有票可售,则售票线程等待
try{wait();}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
available = false;
notify(); //售票后,唤醒存票线程开始存票
}
} class Productor implements Runnable //实现一个接口,生产者(存票)线程类
{
private Tickets t;
public Productor(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<t.size)
t.store();
else
System.exit(0);
}
}
} class Costomer implements Runnable //实现一个接口,消费者(售票)线程类
{
private Tickets t;
public Costomer(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<=t.size)
t.sale();
else
System.exit(0);
}
}
}
class TicketStoreSale
{
public static void main(String[] args)
{
Tickets t = new Tickets(10); Thread t1 = new Thread(new Productor(t));
Thread t2 = new Thread( new Costomer(t)); t1.start();
t2.start();
}
}

方式三:在JDK1.5中提供了多线程升级解决方案。
将同步Synchronized替换成显式的Lock操作。
将Object中的wait,notify,notifyAll,替换成了Conditon对象。
该对象可以对Lock锁,进行获取。
该示例中,实现了本方只唤醒对方操作。

import java.util.concurrent.locks.*;
class Tickets //定义(资源)票类
{
protected int size;//总票数
int number=0; //票号
Boolean available=false;//表示当前是否有票可售
public Tickets(int size)
{
this.size = size;
}
Lock lock = new ReentrantLock(); //创建锁
Condition notFull = lock.newCondition(); //创建未满状态
Condition notEmpty = lock.newCondition();//创建未空状态 public void store() throws InterruptedException //同步方法,实现存票功能
{
lock.lock();
try
{
if(available) //如果线程还有票可售,则存票线程等待
notEmpty.await();
System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
available = true;
notFull.signal();//存票后,唤醒售票线程开始售票
}
finally
{
lock.unlock(); //释放锁资源
}
} public void sale() throws InterruptedException //同步方法,实现售票功能
{
lock.lock();
try
{
if(!available) //如果线程没有票可售,则售票线程等待
notFull.await();
System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
available = false;
notEmpty.signal(); //售票后,唤醒存票线程开始存票
}
finally
{
lock.unlock(); //释放锁资源
}
}
} class Productor implements Runnable //实现一个接口,生产者(存票)线程类
{
private Tickets t;
public Productor(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<t.size)
try
{
t.store();
}
catch (InterruptedException e)
{
e.printStackTrace();
} else
System.exit(0);
}
}
} class Costomer implements Runnable //实现一个接口,消费者(售票)线程类
{
private Tickets t;
public Costomer(Tickets t)
{
this.t = t;
}
public void run()
{
while(true)
{ if(t.number<=t.size)
try
{
t.sale();
}
catch (InterruptedException e)
{
e.printStackTrace();
} else
System.exit(0);
}
}
}
class TicketStoreSaleLock
{
public static void main(String[] args)
{
Tickets t = new Tickets(10); Thread t1 = new Thread(new Productor(t));
Thread t2 = new Thread( new Costomer(t)); t1.start();
t2.start();
}
}

Java:多线程之生产者与消费者的更多相关文章

  1. java多线程解决生产者消费者问题

    import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...

  2. JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止

    JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...

  3. java多线程模拟生产者消费者问题,公司面试常常问的题。。。

    package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...

  4. Java中的生产者、消费者问题

    Java中的生产者.消费者问题描述: 生产者-消费者(producer-consumer)问题, 也称作有界缓冲区(bounded-buffer)问题, 两个进程共享一个公共的固定大小的缓冲区(仓库) ...

  5. Java多线程实现生产者消费者延伸问题

    在操作系统中有一类问题被称为生产者消费者问题:意为,有数个生产者生产产品,有数个消费者消费产品,他们共享一定数量的缓存. 这里用java多线程编程,实现生产者消费者问题的一种延伸,橘子苹果问题. 题目 ...

  6. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

  7. 【多线程】java多线程实现生产者消费者模式

    思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...

  8. Java多线程之生产者消费者问题&lt;一&gt;:使用synchronized keyword解决生产者消费者问题

    今天看了一片博文,讲Java多线程之线程的协作,当中作者用程序实例说明了生产者和消费者问题,但我及其它读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的样例也都存在bug,经过细致研究发现当中的问 ...

  9. JAVA多线程之生产者 消费者模式 妈妈做面包案例

    创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包  最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...

  10. Java多线程_生产者消费者模式2

    在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...

随机推荐

  1. 20145103JAVA第一次实验报告

    20145103<Java程序设计>第一次实验报告 实验内容及其步骤 一.命令行下java程序开发 建立一个java文件,然后在命令行中,对程序进行javac编译,就生成了.class文件 ...

  2. postmortem report of period M1

    一.设想和目标 1.我们的软件主要要解决学长设计的学霸系统中视频及文档的浏览功能问题. 2.时间相对充裕.不过对于我们这些零基础的人来说还是比较困难. 3.我们团队中不同意见通常会进行进一步讨论,说出 ...

  3. C#新语法特性前瞻

    今天逛微软的UserVoice site发现了几个有很有用,也很可能被添加到新版C#中的语法,当然也可能被推迟到下一版,拿出来给大家分享一下. 另外还没投票的可以去为自己最想要的新特性投票,有兴趣的可 ...

  4. jQuery设计思想

    jQuery设计思想 原文网址:http://jqfundamentals.com/book/ 阮一峰 翻译整理 [目录] 一.选择网页元素 二.改变结果集 三.链式操作 四.元素的操作:取值和赋值 ...

  5. web前端网页特效大全导航列表

    CSS3和Html5 图表与图形 表单验证 导航菜单 table选项卡 视频播放器 日期和时间 返回顶部 图层代码 滚动代码 幻灯片 文字特效 图片放大镜 juqery焦点图 瀑布流 广告悬浮代码 在 ...

  6. BZOJ 2820 YY的GCD

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2820 有种方法是枚举质数然后用BZOJ2301来做但是超时了... 具体式子大概张这样: ...

  7. c++ 遍历ini

    inline void CDLG_SET1::EnumIniFile(LPCTSTR pFilePath, CString strKey) { TCHAR strAppNameTemp[];//所有A ...

  8. 威胁远胜“心脏出血”?国外新爆Bash高危安全漏洞

    这几天Linux用户们可能不能愉快地玩耍了,红帽(Redhat)安全团队昨天爆出一个危险的Bash Shell漏洞.其带来的威胁可能比早前披露的“心脏出血”漏洞更大更强! [OpenSSL心脏出血漏洞 ...

  9. C# excel操作

    开源的Excel操作项目: http://www.cnblogs.com/lwme/archive/2011/11/27/2265323.html 添加引用:Microsoft Excel 11.0 ...

  10. 获取app版本号

    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; NSString *name = [infoDiction ...