class ProducerConsumerDemo
{
    public static void main(String[] args)
    {
        Resource r = new Resource();

Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);

t1.start();
        t2.start();
        t3.start();
        t4.start();

}
}

/*
需求:我不想仅仅是两个线程这样同步,我需要很多线程抢资源
这样更快
但出现了问题:这时候线程不遵循你一我一的规律了,直接出错
为什么?
由于线程在wait的地方等待执行,是不需要再次判断条件的

死锁:全部线程都冻结了

怎么做?
重复判断等待条件+全部唤醒

*/

/*
对于多个生产者和消费者。
为什么要定义while判断标记。
原因:让被唤醒的线程再一次判断标记。

为什么定义notifyAll,
因为需要唤醒对方线程。
因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

*/

class Resource
{
    private String name;
    private int count = 1;
    private boolean flag = false;                         /*资源空间的标记,同步的时候必须用到*/
            //  t1    t2
    public synchronized void set(String name)
    {
        while(flag)                                                      /*我需要下面的语句执行完再判断循环条件,就这样做*/
            try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)    /*冻结在这里的,是不需要再次判断条件的,直接运行,没有冻结的需要再次判断条件*/
        this.name = name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
        flag = true;
        this.notifyAll();             /*notify往往唤醒线程中的第一个*/
    }

//  t3   t4  
    public synchronized void out()
    {
        while(!flag)                           
            try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)          
        System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
        flag = false;
        this.notifyAll();                                     /*把全部线程唤醒才可以,相当于整体一的思想,全部唤醒,那么这个线程重复判断条件后,就再次冻结*/
    }
}

class Producer implements Runnable
{
    private Resource res;

Producer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            res.set("+商品+");
        }
    }
}

class Consumer implements Runnable
{
    private Resource res;

Consumer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            res.out();
        }
    }
}

Java线程间通信--生产者消费者的更多相关文章

  1. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  2. 线程间通信--生产者消费者 升级版JDK5

    import java.util.concurrent.locks.*; /*1.新的解锁,上锁操作,据说是jdk5.0升级版,以前的枷锁,解锁都是隐藏的,默认的,现在变成显式 2.新的异常处理方式  ...

  3. Java线程间通信-回调的实现方式

    Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互.   比如举一个简单例子,有一个多线程的 ...

  4. Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.我们来看下相关定义: w ...

  5. java线程间通信:一个小Demo完全搞懂

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.从一个小Demo说起 上篇我们聊到了Java多线程的同步 ...

  6. Java——线程间通信

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. 说说Java线程间通信

    序言 正文 [一] Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在 ...

  8. 说说 Java 线程间通信

    序言 正文 一.Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在一个 ...

  9. java线程间通信1--简单实例

    线程通信 一.线程间通信的条件 1.两个以上的线程访问同一块内存 2.线程同步,关键字 synchronized 二.线程间通信主要涉及的方法 wait(); ----> 用于阻塞进程 noti ...

随机推荐

  1. NGUI学习笔记(三):屏幕自适应

    我们开发移动端游戏的时候,一般都会选择Constrained/FixedSize的缩放模式来保证图片在不同的分辨率下相对于屏幕的尺寸保持一致,但是对于屏幕自适应来说,这还是不够的,不同的手机存在不同的 ...

  2. Css基础-类选择器

    类选择器以一个.显示 <p class="pclass">这是第一个class</p> .pclass { color:red; } <div cla ...

  3. 【转】linux中的sort命令

    转自:http://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html sort是在Linux里非常常用的一个命令,管排序的,集中精力,五分 ...

  4. 声明:function FileSetAttr ( const FileName : string

    对文件和文件夹都有效  FileSetAttr('D:\Administrator\Desktop\patcher\Win32\Release\config\element\update',faHid ...

  5. 给定表达式[x/2] + y + x * y, 其中x,y都是正整数。

    改进了一下,不过还是要十多秒吧. package com.boco.study; import java.math.BigDecimal; import java.util.Calendar; imp ...

  6. Android端如何获取手机当前的网络状态,比如wifi还是3G, 还是2G, 电信还是联通,还是移动

    不多说了,直接看代码, NB人会懂的! package com.example.vdisktest; import android.app.Activity; import android.conte ...

  7. [019]转--C++ operator关键字(重载操作符)

    原博客:http://www.cnblogs.com/speedmancs/archive/2011/06/09/2076873.html operator是C++的关键字,它和运算符一起使用,表示一 ...

  8. 如何打开“USB调试”模式?

    请首先确认您的系统版本, 点击「设置」-「关于手机」查看您当前的手机版本号. 如果您使用的是 Android 3.2及以下系统,请按以下步骤操作: STEP1:在应用列表选择「设置」进入系统设置菜单: ...

  9. SQL 四种连接:内连接、左外连接、右外连接、全连接--转载

    原文:http://zwdsmileface.iteye.com/blog/2191730 个人理解 内连接(INNER JOIN)(典型的连接运算,使用像   =   或   <>   ...

  10. mysql语句在客户端与服务端的基本使用

    //把数据库导出到脚本文件mysqldump -uroot -p1234 --databases abc > d:/a/abc.sql------------------------------ ...