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

黑马程序员_日记18_Java多线程(八)--生产者消费者问题JDK1.5特性

2015-03-30 17:12 471 查看
 ——- android培训java培训、期待与您交流! ———-

生产者消费者问题JDK1.5特性

一、概述

在JDK1.5之前,解决生产者和消费者问题,

用的是synchronized同步+while+notify();

但是这种方法很不安全,很容易让线程全部陷入无限等待状态。

于是我们改用notiyfyAll();来解决。

这样虽然解决了安全问题,但还是存在不足和安全隐患。

notifyAll方法唤醒了线程池中全部的线程,

这并不是我们想要的!

而且,同步套同步很容易发生死锁!

在JDK1.5中提供了显示的锁机制,完美的解决了上述问题。

它既可以做到只唤醒对方线程,而不唤醒己方线程,

又能够让一个锁绑定多个对象!

二、我的代码–JDK1.5新特性解决问题

下面我们首先来看看JDK1.5新特性吧!

还是用2个生产者线程和2个消费者线程来展示。

步骤:

1 查阅API,找到Condition接口和Lock接口

2 定义资源类

3 定义生产者类

4 定义消费者类

5 定义测试类

6 导包

7 检查安全问题

8 测试

9 分析总结

import java.util.concurrent.locks.*;
//一、定义资源类
class Resource
{
private String name;//商品名称
private int count = 1;//商品编号
private boolean flag = false;//资源监视器
private Lock lock = new ReentrantLock();//建立一个锁对象,注意这里只有一把锁。注意,Lock是接口,不可以直接创建对象
private Condition condition_Pro = lock.newCondition();//建立与lock实例一起使用的Condition实例,生产者使用
private Condition condition_Con = lock.newCondition();//建立与lock实例一起使用的Condition实例,消费者使用

//设置商品名称,商品编号自增,并打印设置结果
public void set(String name)throws InterruptedException
{
lock.lock();//生产者线程获取锁。替换原来的synchronized
try
{
while(flag)//当资源监视器为true时,生产者线程等待
condition_Pro.await();//生产者线程等待,并throws InterruptedException
this.name = name;//获取商品名称
System.out.println(Thread.currentThread().getName()+"是生产者线程,生产的商品名称为:"+name+"商品编号为:"+count);
count++;//商品编号自增
flag = true;//把资源监视器改为true
condition_Con.signal();//只唤醒消费者线程
}
finally
{
lock.unlock();//一定要释放锁
}

}

//取出商品,并展示所取出的商品编号
public void get()throws InterruptedException
{
lock.lock();//消费者线程获取锁
try
{
while(!flag)//如果资源监视器为false,消费者线程等待,并抛出InterruptedException
condition_Con.await();
System.out.println(Thread.currentThread().getName()+"是消费者线程,消费的商品名称为:"+name+"商品编号为:......."+count);
flag = false;//把资源监视器改为false
condition_Pro.signal();//只唤醒生产者线程
}
finally
{
lock.unlock();//一定要释放锁
}
}
}

//二、定义生产者类
class Producer implements Runnable
{
private Resource r;//引用Resource类型变量r

//重载构造函数,避免建立多个对象
Producer(Resource r)
{
this.r = r;
}

//覆盖run方法
public void run()
{
try
{
while(true)//让生产者一直在生产
r.set("商品");
}
catch (InterruptedException e)
{
//暂不处理,以利于观察结果
}

}

}

//三、定义消费者类
class Consumer implements Runnable
{
private Resource r;//引用Resource类型变量r

//重载构造函数,和生产者线程使用同一资源对象
Consumer(Resource r)
{
this.r =r;
}

//覆盖run方法
public void run()
{
try
{
while(true)//让消费者一直取商品
r.get();
}
catch (InterruptedException e)
{
//暂不处理,方便观察
}
}
}

//四、定义测试类
class MyProducerConsumerDemo2
{
public static void main(String[] args)
{
Resource r = new Resource();//建立资源
Producer p = new Producer(r);//建立生产者
Consumer c= new Consumer(r);//建立消费者
Thread tp1 = new Thread(p);//建立生产者线程1
Thread tp2 = new Thread(p);//建立生产者线程2
Thread tp3 = new Thread(p);//建立生产者线程3
Thread tc1 = new Thread(c);//建立消费者线程1
Thread tc2 = new Thread(c);//建立消费者线程2
Thread tc3 = new Thread(c);//建立消费者线程3
tp1.start();//启动生产者线程1
tp2.start();//启动生产者线程2
tp3.start();//启动生产者线程3
tc1.start();//启动消费者线程1
tc2.start();//启动消费者线程2
tc3.start();//启动生产者线程3
}
}


运行结果显示正常!

三、分析总结JDK1.5新特性

JDK1.5定义了显示的锁机制

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。

此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。

将同步操作synchronized替换成了Lock接口

将object中的wait,notify,notifyAll,替换成了Condition对象

在本示例中,实现了只唤醒对方线程,而不会唤醒己方线程。

实现了一个锁lock绑定了两个对象condition_Pro和condition_Con。

注意:

lock和condition都是接口,不可以直接创建对象。

在这里创建Lock对象利用了ReentrantLock类

创建condition对象利用了ReentrantLock类中的newCondition方法。

ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用synchronized 方法和语句

所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐