对于同步代码块,对于锁的操作是隐式的
但是在JDK1.5之前的这种方法效率有点低,判断会很多,后面升级之后有新的解决方案

jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作

Lock接口:替代了同步代码块或者同步函数,将同步的隐式锁操作变成显示锁操作,同时更为灵活,可以一个锁上加上多组监视器

     lock():获取锁       unlock():释放锁,通常定义在finally代码块中

Condition接口:替代了Object中的wait notify notifyAll方法,将这些监视器方法单独封装,变成了Condition监视器对象,可以喝任意锁组合

        await();    singal();       singalAll();

同步代码块到lock的变化:

 import java.util.concurrent.locks.*;//lock在此包中
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
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(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock();//创建一个锁对象 public void set(String name){
lock.lock();
try{
while(flag)
try{this.wait();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
notifyAll();
}finally{
lock.unlock();
} } public void out(){
lock.lock();
try{
while(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
flag = true;
notifyAll();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}

上述实例中锁换成了lock之后就不能用this来操作wait等方法了,应该用lock锁中的Condition接口中的方法,该接口将Object监视器方法(wait,notify,notifyAll)分解成不同的对象

 import java.util.concurrent.locks.*;
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
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(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
Condition con = lock.newCondition(); public void set(String name){
lock.lock();
try{
while(flag)
try{con.await();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
con.signalAll(); }finally{
lock.unlock();
}
} public void out(){
lock.lock();
try{
while(!flag)
try{con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); flag = true;
con.signalAll();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}

上述实例只有一组监视器,既监视着生产者,又监视着消费者,可以搞两个监视器,一组监视生产者,一组监视消费者

 import java.util.concurrent.locks.*;
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
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(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock(); /*
通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
Condition con = lock.newCondition();
*/ //通过已有的锁获取监视器对象(两组),一组监视生产者,一组监视消费者
Condition Producer_con = lock.newCondition();
Condition Consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
try{
while(flag)
try{Producer_con.await();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
//con.signalAll();//会发生死锁,所以要用到notifyAll
Consumer_con.signa();//有了两组监视器后就不用signaAll方法唤醒所有线程池中的线程了,只唤醒对方的一个线程,这样效率就高很多了
}finally{
lock.unlock();
}
} public void out(){
lock.lock();
try{
while(!flag)
try{Consumer_con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); flag = true;
//con.signalAll(); Producer_con.signal();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}

wait和sleep的区别:

wait和sleep都是让线程处于冻结状态的方法
区别:
  1.wait可以指定时间也可以不指定。sleep必须指定时间。
  2.在同步中时,对CPU的执行权和锁的处理不同.wait:释放执行权,释放锁。sleep:释放执行权,不释放锁(不同中的代码必须拿到锁才能运行)

  3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围
     synchronized(x){
          x.notify()
         //或者wait()
     }
      4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock的更多相关文章

  1. Java-JUC(九):使用Lock替换synchronized,使用Condition的await,singal,singalall替换object的wait,notify,notifyall实现线程间的通信

    Condition: condition接口描述了可能会与锁有关的条件变量.这些用法上与使用object.wait访问隐式监视器类似,但提供了更强大的功能.需要特别指出的是,单个lock可能与多个Co ...

  2. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  3. Java核心知识点学习----多线程并发之线程间的通信,notify,wait

    1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...

  4. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  5. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  6. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  7. C# 线程间互相通信

    C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent. 一.AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过 ...

  8. QThread与其他线程间相互通信

    转载请注明链接与作者huihui1988 QThread的用法其实比较简单,只需要派生一个QThread的子类,实现其中的run虚函数就大功告成, 用的时候创建该类的实例,调用它的start方法即可. ...

  9. Handler不同线程间的通信

    转http://www.iteye.com/problems/69457 Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程( ...

随机推荐

  1. jqgrid表头上面再加一行---二级表头

    实现效果如图,代码如下: $( "#table_list_1" ).jqGrid( 'setGroupHeaders' , { useColSpanStyle : true , / ...

  2. 深度学习论文翻译解析(二):An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition

    论文标题:An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application ...

  3. 前端开发环境之GRUNT自动WATCH压缩JS文件与编译SASS文件环境下Ruby安装sass常见错误分析

    前言: 1.sass编译为css文件,早先时刻写css,后来看了sass挺不错的,于是在新的项目中开始使用上了sass.(grunt需要ruby环境,所以需要先安装ruby,sass环境) ①安装ru ...

  4. xshell与xftp使用注意

    1.xshell报ssh服务器拒绝了密码,请再试一次 xshell登录使用的用户名不能是root,要是服务器的用户名,否则连接时会报 ssh服务器拒绝了密码,请再试一次.将root改成服务器用户名即可 ...

  5. 第4章 ext文件系统机制原理剖析

    将磁盘进行分区,分区是将磁盘按柱面进行物理上的划分.划分好分区后还要进行格式化,然后再挂载才能使用(不考虑其他方法).格式化分区的过程其实就是创建文件系统. 文件系统的类型有很多种,如CentOS 5 ...

  6. Linux进程间通信(System V) --- 信号量

    信号量 IPC 原理 信号量通信机制主要用来实现进程间同步,避免并发访问共享资源.信号量可以标识系统可用资源的个数.最简单的信号量为二元信号量 下图为 Linux 信号量通信机制的概念图.在实际应用中 ...

  7. Ado.net怎么执行存储过程?

    与ADO.Net执行SQL语句的地方只有两点不同1.使用存储过程名代替sql语句2. 使用查询对象SqlCommand,需配置一个CommandType属性 存储过程的执行语法-> exec 存 ...

  8. JS 上传图片 + 预览功能(二)

    简单粗暴 直接进入主题: Html <script src="../js/jquery-2.1.1.min.js"></script> <style& ...

  9. 10.C++-构造函数初始化列表、类const成员、对象构造顺序、析构函数

    首先回忆下,以前学的const 单独使用const修饰变量时,是定义的常量,比如:const int i=1; 使用volatile const修饰变量时,定义的是只读变量 使用const & ...

  10. Python 实现的 12306抢票脚本

    Python12306抢票脚本 本脚本使用一个类来实现所有代码,大体上分为以下几个模块及其步骤:- 初始化对象属性(在抢票前进行的属性初始化,包括初始化浏览器模拟对象,个人信息等).- 建立模拟浏览器 ...