码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-03-30 18:49:32      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:多线程   jdk1-5新特性   生产者消费者问题   

 ——- 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 方法和语句
所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

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

标签:多线程   jdk1-5新特性   生产者消费者问题   

原文地址:http://blog.csdn.net/itheima_1llt/article/details/44753591

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!