假设有这样一种情况,有一个桌子,桌子上面有一个盘子,盘子里只能放一颗鸡蛋,A专门往盘子里放鸡蛋,如果盘子里有鸡蛋,则一直等到盘子里没鸡蛋,B专门从盘子里拿鸡蛋,如果盘子里没鸡蛋,则等待直到盘子里有鸡蛋。其实盘子就是一个互斥区,每次往盘子放鸡蛋应该都是互斥的,A的等待其实就是主动放弃锁,B 等待时还要提醒A放鸡蛋。
如何让线程主动释放锁
很简单,调用锁的wait()方法就好。wait方法是从Object来的,所以任意对象都有这个方法。

import java.util.ArrayList;
import java.util.List; public class Plate { List<Object> eggs = new ArrayList<Object>(); public synchronized Object getEgg() {
while(eggs.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
}
} Object egg = eggs.get(0);
eggs.clear();// 清空盘子
notify();// 唤醒阻塞队列的某线程到就绪队列
System.out.println("拿到鸡蛋");
return egg;
} public synchronized void putEgg(Object egg) {
while(eggs.size() > 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
eggs.add(egg);// 往盘子里放鸡蛋
notify();// 唤醒阻塞队列的某线程到就绪队列
System.out.println("放入鸡蛋");
} static class AddThread extends Thread{
private Plate plate;
private Object egg=new Object();
public AddThread(Plate plate){
this.plate=plate;
} public void run(){
for(int i=0;i<5;i++){
plate.putEgg(egg);
}
}
} static class GetThread extends Thread{
private Plate plate;
public GetThread(Plate plate){
this.plate=plate;
} public void run(){
for(int i=0;i<5;i++){
plate.getEgg();
}
}
} public static void main(String args[]){
try {
Plate plate=new Plate();
Thread add=new Thread(new AddThread(plate));
Thread get=new Thread(new GetThread(plate));
add.start();
get.start();
add.join();
get.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("测试结束");
}
}
import java.util.ArrayList;
import java.util.List; public class Plate { List<Object> eggs = new ArrayList<Object>(); public synchronized Object getEgg() {
while(eggs.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
}
} Object egg = eggs.get(0);
eggs.clear();// 清空盘子
notify();// 唤醒阻塞队列的某线程到就绪队列
System.out.println("拿到鸡蛋");
return egg;
} public synchronized void putEgg(Object egg) {
while(eggs.size() > 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
eggs.add(egg);// 往盘子里放鸡蛋
notify();// 唤醒阻塞队列的某线程到就绪队列
System.out.println("放入鸡蛋");
} static class AddThread extends Thread{
private Plate plate;
private Object egg=new Object();
public AddThread(Plate plate){
this.plate=plate;
} public void run(){
for(int i=0;i<5;i++){
plate.putEgg(egg);
}
}
} static class GetThread extends Thread{
private Plate plate;
public GetThread(Plate plate){
this.plate=plate;
} public void run(){
for(int i=0;i<5;i++){
plate.getEgg();
}
}
} public static void main(String args[]){
try {
Plate plate=new Plate();
Thread add=new Thread(new AddThread(plate));
Thread get=new Thread(new GetThread(plate));
add.start();
get.start();
add.join();
get.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("测试结束");
}
}

  

执行结果:

Html代码

  1. 放入鸡蛋
  2. 拿到鸡蛋
  3. 放入鸡蛋
  4. 拿到鸡蛋
  5. 放入鸡蛋
  6. 拿到鸡蛋
  7. 放入鸡蛋
  8. 拿到鸡蛋
  9. 放入鸡蛋
  10. 拿到鸡蛋
  11. 测试结束

声明一个Plate对象为plate,被线程A和线程B共享,A专门放鸡蛋,B专门拿鸡蛋。假设
1 开始,A调用plate.putEgg方法,此时eggs.size()为0,因此顺利将鸡蛋放到盘子,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列还没有线程。
2 又有一个A线程对象调用plate.putEgg方法,此时eggs.size()不为0,调用wait()方法,自己进入了锁对象的阻塞队列。
3 此时,来了一个B线程对象,调用plate.getEgg方法,eggs.size()不为0,顺利的拿到了一个鸡蛋,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列有一个A线程对象,唤醒后,它进入到就绪队列,就绪队列也就它一个,因此马上得到锁,开始往盘子里放鸡蛋,此时盘子是空的,因此放鸡蛋成功。
4 假设接着来了线程A,就重复2;假设来料线程B,就重复3。 
整个过程都保证了放鸡蛋,拿鸡蛋,放鸡蛋,拿鸡蛋。

生产者与消费者---demo2---boke的更多相关文章

  1. 第3月第2天 find symbolicatecrash 生产者-消费者 ice 引用计数

    1.linux find export find /Applications/Xcode.app/ -name symbolicatecrash -type f export DEVELOPER_DI ...

  2. LMAX Disruptor—多生产者多消费者中,消息复制分发的高性能实现

    解决的问题 当我们有多个消息的生产者线程,一个消费者线程时,他们之间如何进行高并发.线程安全的协调? 很简单,用一个队列. 当我们有多个消息的生产者线程,多个消费者线程,并且每一条消息需要被所有的消费 ...

  3. JAVA并发框架之Semaphore实现生产者与消费者模型

    分类: Java技术      锁和信号量(Semaphore)是实现多线程同步的两种常用的手段.信号量需要初始化一个许可值,许可值可以大于0,也可以小于0,也可以等于0.      如果大于0,表示 ...

  4. java 22 - 19 多线程之生产者和消费者的代码优化

    在之前,是把生产者录入数据和消费者获取数据的所有代码都分别写在各自的类中. 这样不大好 这次把生产者和消费者部分关键代码都写入资源类中: package zl_Thread; public class ...

  5. java 22 - 16 多线程之生产者和消费者的问题

    生产者和消费者问题的描述图 通过上图,我们可以发现: 生产者和消费者使用的都是同一个资源(肉包子) 所以,当使用线程的时候,这两类的锁也是同一把锁(为了避免出现线程安全问题) 例子:学生信息的录入和获 ...

  6. Java实现生产者和消费者

    生产者和消费者问题是操作系统的经典问题,在实际工作中也常会用到,主要的难点在于协调生产者和消费者,因为生产者的个数和消费者的个数不确定,而生产者的生成速度与消费者的消费速度也不一样,同时还要实现生产者 ...

  7. 线程操作案例--生产者与消费者,Object类对线程的支持

    本章目标 1)加深对线程同步的理解 2)了解Object类中对线程的支持方法. 实例 生产者不断生产,消费者不断消费产品. 生产者生产信息后将其放到一个区域中,之后消费者从区域中取出数据. 既然生产的 ...

  8. linux第13天 生产者与消费者

    pthread_cond_t   my_condition = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INIT ...

  9. java多线程中的生产者与消费者之等待唤醒机制@Version1.0

    一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒:    Object类中提供了三个方法:    wait():等待    notify():唤醒单个线程    notify ...

  10. C# 线程(四):生产者和消费者

    From : http://kb.cnblogs.com/page/42530/ 前面说过,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时 ...

随机推荐

  1. python爬取糗事百科段子

    初步爬取糗事百科第一页段子(发布人,发布内容,好笑数和评论数) #-*-coding:utf--*- import urllib import urllib2 import re page = url ...

  2. MVC 控件系列

    下拉框:@Html.DropDownList("GroupId"); 文本框:@Html.TextBox("RoleCode", "", n ...

  3. 修改SpringBoot 默认的小叶子图标

    Springboot 项目,在浏览器中访问时,浏览器上导航栏的图标是一片绿色的叶子,我们可以修改它. 将格式为.ico的图片放入以下任一项目文件夹即可.但,图片命名必须为favicon.ico 1.类 ...

  4. Codeforces Round #435 (Div. 2) c+d

    C:给n和k要求,找出n个不同的数,使得亦或起来等于k 可以先预处理从1到1e5,找亦或起来等于(11111111111111111)(二进制)的所有对数,然后四个一起亦或就是0了,再和k亦或 可以看 ...

  5. Sublime Text 3总是出现“1 missing dependency was just installed.”

    Sublime Text 3总是出现“1 missing dependency was just installed.” 原因及结果 https://github.com/wbond/package_ ...

  6. 编译内核时覆盖KBUILD_BUILD_USER和KBUILD_BUILD_HOST

    默认情况下make kernel.img编译出来的内核在/proc/version中显示的内容是: Linux version 3.0.36+ (xxx@yyyy) (gcc version 4.6. ...

  7. URL格式和urlencode

    URL的格式:protocol :// hostname[:port] / path / [;parameters][?query]#fragment URL出现了有+,空格,/,?,%,#,& ...

  8. lucene搜索之facet查询原理和facet查询实例——TODO

    转自:http://www.lai18.com/content/7084969.html Facet说明 我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为 ...

  9. cmd命令之查看进程到杀掉进程

    1. cmd命令查看当前进程 netstat -ano | findstr “port”

  10. js字符串和数组操作,容易混淆的方法总结(slice、substring、substr、splice)

    平时工作中,很少静下心来总结基础知识,总觉得自己会用了,有点飘了,直到碰壁之后才懂得基础知识的重要性.大牛告诉我,一次写对,是不是可以不用F12去调试了?是不是省了时间?简直是面红耳赤,无地自容.在这 ...