Java:多线程之生产者与消费者
2015-10-27 21:48
344 查看
要求:用两个线程模拟存票、售票过程。但要求每存入一张票,就售出一张票,售出后,再存入,直到售完为止。
用到的知识点:线程等待、唤醒、可能的线程中断异常
下面的方式一和方式二采用的是唤醒所有等待的线程,即wait()和notify()方法
方式一:继承Thread
方式二:实现Runnable接口
方式三:在JDK1.5中提供了多线程升级解决方案。
将同步Synchronized替换成显式的Lock操作。
将Object中的wait,notify,notifyAll,替换成了Conditon对象。
该对象可以对Lock锁,进行获取。
该示例中,实现了本方只唤醒对方操作。
用到的知识点:线程等待、唤醒、可能的线程中断异常
下面的方式一和方式二采用的是唤醒所有等待的线程,即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 Vamei快速教程11 对象引用
- 矩阵------顺时针打印矩阵+顺时针旋转矩阵+之字形打印矩阵(Java)
- java工厂模式
- Eclipse 工作目录被破坏,导致Eclipse 打不开
- Java:多线程
- .以及JDK1.5ConcurrentHashMap新特性
- 记录-Head first java-1到3章
- java中Iterator和Iterable的区别
- Spring controller
- 1、Ant编译一般Java项目的步骤
- Java 对类中的属性使用set/get方法的意义和用法
- 在eclipse 上配置maven
- java Vamei快速教程10 接口的继承和抽象类
- eclipse中android结构整理
- 整合spring,springmvc和mybatis
- Java Enum详解
- JDK 源码解析 —— Integer
- java Vamei快速教程09 类数据和类方法
- Java:包的使用Pack
- java第五章 子类与继承