对于同步代码块,对于锁的操作是隐式的
但是在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. PHP的UTF-8中文转拼音处理类

    <?php /** * PHP 汉字转拼音 * @author Jerryli(hzjerry@gmail.com) * @version V0.20140715 * @package SPFW ...

  2. 一个复杂Json的解析

    { "website": { "1": { "basic": { "homepage": "http://py ...

  3. noip之后的一些感受

    你经历过绝望吗,那种希望完全破碎,眼前看不到光亮,不知道下一步怎么走,不知道接下来应该如何生活的那种绝望? 我经历过. 2018.11.12 下午 秦皇岛到石家庄的高铁上 听着同学兴高采烈的讨论,自己 ...

  4. SpringMVC4+MyBatis+SQL Server2014实现读写分离

    前言 基于mybatis的AbstractRoutingDataSource和Interceptor用拦截器的方式实现读写分离,根据MappedStatement的boundsql,查询sql的sel ...

  5. Asp.net中GridView详解《转》

    ASP.NET服务器控件GridView 1         ASP.NET 服务器控件GridView使用 本教程不介绍服务器端控件的呈现,事件处理,状态等理论知识,只介绍服务器端控件的使用操作,如 ...

  6. 4.移植uboot-使uboot支持DM9000网卡

    在上一章,使uboot能够支持nor.nand 本节继续修改让uboot支持DM9000C网卡,便可以通过网络来传输文件 首先uboot已带有dm9000网卡的驱动,位于drivers/net/下的d ...

  7. java Future用法和意义一句话击破

    在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果. 所以run的返回值是void类型. 如果是一个多线程协作程序,比如菲波拉切数列,1,1,2,3,5,8...使 ...

  8. linux部分常见指令

    游走指令 cd: 进入指定位置 cd /   进入到根目录   cd /home   进入到home文件夹 cd - 进入上次所在文件夹    比如  在 / 时 cd /usr/local到loca ...

  9. 牛客网剑指offer 二维数组的查找

    题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 解题思路 该题有很多种 ...

  10. hive的行列转换

    行转列(把多个行合并) 比如把: id    tag 1 12 1 23 2 67 2  78 2 76 行转列之后: id tag 1 12,23 2 67,78,76 使用函数为:concat_w ...