本文讲述Java中的线程同步和生产者消费者问题,其中主要涉及线程同步和wait()、notify()方法的用法。

wait和notify方法只能用在线程同步中,wait和notify是object的方法,因此任何对象都能调用,当一个线程中调用wait方法时会将该线程阻塞,将cpu资源让给其他线程,关键的一点是在线程阻塞前会将持有的锁释放,这一点是和sleep方法的很大区别,sleep方法使线程睡眠的话是不会主动释放锁的,直到sleep时间到或被中断线程唤醒。wait方法将持有的锁释放然后阻塞调用该wait方法的线程,直到设置的wait时间耗尽或者被notify唤醒重新持有锁,调用wait的线程被阻塞后,CPU执行其他线程,在其他线程中调用了notify或notifyAll后会唤醒被阻塞的线程。

生产者消费者问题中,有一个先后问题,必须先生产再消费,要吃饭必须先种出稻谷,生产者和消费者问题和Linux的应用编程中的竞争互斥问题是一样的。生产为一个线程,消费为一个线程,有一个仓库存放产品,生产出的产品放在仓库中,要消费也要去仓库中取产品,所以生产线程和消费线程是共同持有仓库这个锁的。当生产者持有锁的时候不能消费,在消费线程持有锁的时候不能生产。当仓库满了以后还意图继续生产则调用wait将生产线程阻塞,释放锁,将CPU让给消费线程,消费线程消费了产品以后仓库不再是满的状态,然后消费线程调用notify唤醒生产线程可以继续生产,当消费线程执行完以后释放锁,生产线程唤醒了重新获得了刚被消费线程释放的锁,然后生产线程就可以继续执行了;(^_^)当消费线程将仓库中的产品消费完后,消费线程意图再次消费却发现仓库空了不能消费,所以调用wait释放锁将自己阻塞,生产线程获得cpu执行权和锁去生产产品,生产了产品以后放到仓库调用notify唤醒消费线程,告诉消费线程仓库有东东了,你可以去消费了,当然是要等生产线程执行完释放锁以后消费线程才有机会重新获得锁并去消费。

import java.util.*;
public class lesson911 {
public static void main(String [] args) {
StoreHouse sh = new StoreHouse();
Producer p =new Producer(sh); //创建生产者线程
Consumer c = new Consumer(sh); //创建消费线程
new Thread(p).start(); //启动线程
new Thread(c).start(); //无论哪个线程先启动都必须是先生产再消费 }
} class Product { //产品
int id;
Product(int id) {
this.id = id;
}
public String toString() { //重新定义toString方法,其实这个程序中不需要,没用到。
return "product:"+id;
} }
class StoreHouse { //定义仓库
Product [] ArrProduct = new Product[6]; //仓库只能容纳6个产品
int index=0;
int num_push=0,num_pop=0;
public synchronized void push(Product product) { //生产:将产品放到仓库
while(index==ArrProduct.length) {
try {
System.out.println("$$仓库满了$$(^_^)");
this.wait(); //当仓库满了以后调用wait,阻塞意图再次生产的线程。 }catch(InterruptedException e) {
e.printStackTrace();
}
}
this.notify(); //正常生产,调用notify通知消费线程仓库已有产品可去仓库消费
//System.out.println("notify 消费者");
ArrProduct[index] = product;
index++;
num_push++;
System.out.println("####生产了产品###:"+(num_push-1));
}
public synchronized Product pop() { //消费:将产品从仓库取出
while(index==0) {
try {
System.out.println("&&仓库空了&&(@_@)");
this.wait(); //当仓库空了以后,调用wait阻塞意图再次消费的消费线程
}catch(InterruptedException e) {
e.printStackTrace();
}
}
this.notify(); //正常消费,调用notify告诉生产线程现在仓库已经有空位可以继续生产
// System.out.println("notify 生产者");
index--;
num_pop++;
System.out.println("*******消费了产品*******:"+(num_pop-1));
return ArrProduct[index];
} }
class Producer implements Runnable { //生产者线程
StoreHouse sh = null;
Producer(StoreHouse sh) { //生产线程和消费线程都是操作的同一个仓库。
this.sh = sh;
} public void run() { for(int i=0;i<15;i++) {
Product product = new Product(i);
sh.push(product); //往仓库中添加产品 try {
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
} class Consumer implements Runnable { //消费者线程
StoreHouse sh = null;
Consumer(StoreHouse sh) {
this.sh = sh;
} public void run() { for(int i=0;i<15;i++) {
Product product = sh.pop(); try {
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e) {
e.printStackTrace();
} }
}
}

运行结果如下图所示




初识Java--线程同步(2)的更多相关文章

  1. java 线程同步 原理 sleep和wait区别

    java线程同步的原理java会为每个Object对象分配一个monitor, 当某个对象(实例)的同步方法(synchronized methods)被多个线程调用时,该对象的monitor将负责处 ...

  2. Java线程同步_1

    Java线程同步_1 synchronized 该同步机制的的核心是同步监视器,任何对象都可以作为同步监视器,代码执行结束,或者程序调用了同步监视器的wait方法会导致释放同步监视器 synchron ...

  3. Java线程同步之一--AQS

    Java线程同步之一--AQS 线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序.同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务.每个服务员在同一时刻 ...

  4. java线程 同步临界区:thinking in java4 21.3.5

    java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...

  5. JAVA - 线程同步和线程调度的相关方法

    JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...

  6. Java线程同步的四种方式详解(建议收藏)

    ​ Java线程同步属于Java多线程与并发编程的核心点,需要重点掌握,下面我就来详解Java线程同步的4种主要的实现方式@mikechen 目录 什么是线程同步 线程同步的几种方式 1.使用sync ...

  7. Java线程同步和线程通信

    一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...

  8. 【总结】Java线程同步机制深刻阐述

    原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread ...

  9. Java线程同步的方式

     java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),      将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的 ...

  10. Java线程同步(synchronized)——卖票问题

    卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1, ...

随机推荐

  1. MSBI常见问题总结

    SSIS 1.对连接管理器“DC”的AcquireConnection方法调用失败,错误代码0xC0209303.可能在此之前已经发出错误消息,提供了有关AcquireConnection方法调用失败 ...

  2. Oracle EBS-SQL (BOM-16):检查多层BOM.sql

    select rownum seq_num, lpad(to_char(level), decode(level, 1, 1, level + 1), '.') bom_level, bbm.ASSE ...

  3. let区别(关于racket和r5rs)

    R5RS is the Revised5 Report on the Algorithmic Language Scheme.参考http://www.schemers.org/Documents/S ...

  4. Ajax请求ashx返回各类数据的常见处理方式

    .请求text数据,在success事件中手动解析 前台: $.ajax({ type: "post", url: "checkFile.ashx", data ...

  5. 泛泰A900 刷4.4专用中文TWRP2.7.1.1版 支持自己主动识别手机版本号(全球首创)

    因本人手上的A900S已砖, 所以临时弄不了ROM了, 先上传之前已经弄好的刷4.4专用的新版TWRP recovery 2.7.1.1  这个版本号是我自己定义的,为差别之前公布的2.7.0.0版( ...

  6. About Quick Packaging and Custom Packaging

    About Quick Packaging and Custom Packaging The Enterprise Manager Support Workbench provides two met ...

  7. (转)ASP.NET缓存概念及其应用浅析

    ASP.NET缓存概念及其应用浅析 ASP.NET缓存是什么呢?ASP.NET缓存有什么样子的特点呢?本文就向你详细介绍ASP.NET缓存的相关情况. ASP.NET缓存概念是什么呢?通常,应用程序可 ...

  8. css系列教程--文本

    text-align:规定文本的水平对齐方式.left/right/center/justify(两端对齐)/inherit(继承) text-decoration:添加到文本的效果.下划线,中间线等 ...

  9. (三)Android中Intent概念及应用

    一.显示Intent startActivity(new Intent(MainActivity.this,BAty.class)); 显示Intent直接指定要启动的Intent类 注意自己通过创建 ...

  10. SQL查询练习题目

    SQL查询练习题目 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表(四)所示 ...