您的位置:首页 > 编程语言 > Java开发

Java:多线程之生产者与消费者

2015-10-27 21:48 344 查看
要求:用两个线程模拟存票、售票过程。但要求每存入一张票,就售出一张票,售出后,再存入,直到售完为止。

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

下面的方式一和方式二采用的是唤醒所有等待的线程,即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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: