面试题:

两个线程,一个线程打印1-52,另一个打印字母A-Z打印顺序为12A34B...5152Z,

要求用线程间通信

线程间通信:1、生产者+消费者2、通知等待唤醒机制

多线程编程模版中

1、判断

2、干活

3、唤醒

synchronized实现

  1. package com.atguigu.thread;
  2.  
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;
  6.  
  7. import org.omg.IOP.Codec;
  8.  
  9.  
  10. class ShareDataOne//资源类
  11. {
  12.   private int number = 0;//初始值为零的一个变量
  13.  
  14.   public synchronized void increment() throws InterruptedException 
  15.   {
  16.      //1判断
  17.      if(number !=0 ) {
  18.        this.wait();
  19.      }
  20.      //2干活
  21.      ++number;
  22.      System.out.println(Thread.currentThread().getName()+"\t"+number);
  23.      //3通知
  24.      this.notifyAll();
  25.   }
  26.   
  27.   public synchronized void decrement() throws InterruptedException 
  28.   {
  29.      // 1判断
  30.      if (number == 0) {
  31.        this.wait();
  32.      }
  33.      // 2干活
  34.      --number;
  35.      System.out.println(Thread.currentThread().getName() + "\t" + number);
  36.      // 3通知
  37.      this.notifyAll();
  38.   }
  39. }
  40.  
  41. /**
  42.  * 
  43.  * @Description:
  44.  *现在两个线程,
  45.  * 可以操作初始值为零的一个变量,
  46.  * 实现一个线程对该变量加1,一个线程对该变量减1,
  47.  * 交替,来10轮。 
  48.  * @author xialei
  49.  *
  50.  *  * 笔记:Java里面如何进行工程级别的多线程编写
  51.  * 1 多线程变成模板(套路)-----上
  52.  *     1.1  线程    操作    资源类  
  53.  *     1.2  高内聚  低耦合
  54.  * 2 多线程变成模板(套路)-----下
  55.  *     2.1  判断
  56.  *     2.2  干活
  57.  *     2.3  通知
  58.  
  59.  */
  60. public class NotifyWaitDemoOne
  61. {
  62.   public static void main(String[] args)
  63.   {
  64.      ShareDataOne sd = new ShareDataOne();
  65.      new Thread(() -> {
  66.        for (int i = 1; i < 10; i++) {
  67.           try {
  68.             sd.increment();
  69.           } catch (InterruptedException e) {
  70.             // TODO Auto-generated catch block
  71.             e.printStackTrace();
  72.           }
  73.        }
  74.      }, "A").start();
  75.      new Thread(() -> {
  76.        for (int i = 1; i < 10; i++) {
  77.           try {
  78.             sd.decrement();
  79.           } catch (InterruptedException e) {
  80.             // TODO Auto-generated catch block
  81.             e.printStackTrace();
  82.           }
  83.        }
  84.      }, "B").start();
  85.   }
  86. }
  87. /*
  88.  * * 
  89.  * 2 多线程变成模板(套路)-----下
  90.  *     2.1  判断
  91.  *     2.2  干活
  92.  *     2.3  通知
  93.  * 3 防止虚假唤醒用while
  94.  * 
  95.  * 
  96.  * */
  97.  

换成4个线程会导致错误,虚假唤醒

原因:在java多线程判断时,不能用if,程序出事出在了判断上面,

突然有一添加的线程进到if了,突然中断了交出控制权,

没有进行验证,而是直接走下去了,加了两次,甚至多次

解决虚假唤醒:查看API,java.lang.Object

中断和虚假唤醒是可能产生的,所以要用loop循环,if只判断一次,while是只要唤醒就要拉回来再判断一次。if换成while

java8实现

  1. Condition:查看APIjava.util.concurrent

  2.  
  3. class BoundedBuffer {
  4.    final Lock lock = new ReentrantLock();
  5.    final Condition notFull  = lock.newCondition(); 
  6.    final Condition notEmpty = lock.newCondition(); 

  7.    final Object[] items = new Object[100];
  8.    int putptr, takeptr, count;

  9.    public void put(Object x) throws InterruptedException {
  10.      lock.lock();
  11.      try {
  12.        while (count == items.length)
  13.          notFull.await();
  14.        items[putptr] = x;
  15.        if (++putptr == items.length) putptr = 0;
  16.        ++count;
  17.        notEmpty.signal();
  18.      } finally {
  19.        lock.unlock();
  20.      }
  21.    }
  22.  

线程间定制化调用通信

  1. package com.atguigu.thread;

  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;


  5. class ShareResource
  6. {
  7.   private int number = 1;//1:A 2:B 3:C 
  8.   private Lock lock = new ReentrantLock();
  9.   private Condition c1 = lock.newCondition();
  10.   private Condition c2 = lock.newCondition();
  11.   private Condition c3 = lock.newCondition();

  12.   public void print5(int totalLoopNumber)
  13.   {
  14.      lock.lock();
  15.      try 
  16.      {
  17.        //1 判断
  18.        while(number != 1)
  19.        {
  20.           //A 就要停止
  21.           c1.await();
  22.        }
  23.        //2 干活
  24.        for (int i = 1; i <=5; i++) 
  25.        {
  26.           System.out.println(Thread.currentThread().getName()+"\t"+i+"\t totalLoopNumber: "+totalLoopNumber);
  27.        }
  28.        //3 通知
  29.        number = 2;
  30.        c2.signal();
  31.      } catch (Exception e) {
  32.        e.printStackTrace();
  33.      } finally {
  34.        lock.unlock();
  35.      }
  36.   }
  37.   public void print10(int totalLoopNumber)
  38.   {
  39.      lock.lock();
  40.      try 
  41.      {
  42.        //1 判断
  43.        while(number != 2)
  44.        {
  45.           //A 就要停止
  46.           c2.await();
  47.        }
  48.        //2 干活
  49.        for (int i = 1; i <=10; i++) 
  50.        {
  51.           System.out.println(Thread.currentThread().getName()+"\t"+i+"\t totalLoopNumber: "+totalLoopNumber);
  52.        }
  53.        //3 通知
  54.        number = 3;
  55.        c3.signal();
  56.      } catch (Exception e) {
  57.        e.printStackTrace();
  58.      } finally {
  59.        lock.unlock();
  60.      }
  61.   }  
  62.   
  63.   public void print15(int totalLoopNumber)
  64.   {
  65.      lock.lock();
  66.      try 
  67.      {
  68.        //1 判断
  69.        while(number != 3)
  70.        {
  71.           //A 就要停止
  72.           c3.await();
  73.        }
  74.        //2 干活
  75.        for (int i = 1; i <=15; i++) 
  76.        {
  77.           System.out.println(Thread.currentThread().getName()+"\t"+i+"\t totalLoopNumber: "+totalLoopNumber);
  78.        }
  79.        //3 通知
  80.        number = 1;
  81.        c1.signal();
  82.      } catch (Exception e) {
  83.        e.printStackTrace();
  84.      } finally {
  85.        lock.unlock();
  86.      }
  87.   }  
  88. }


  89. /**
  90.  * 
  91.  * @Description: 
  92.  * 多线程之间按顺序调用,实现A->B->C
  93.  * 三个线程启动,要求如下:
  94.  * 
  95.  * AA打印5次,BB打印10次,CC打印15次
  96.  * 接着
  97.  * AA打印5次,BB打印10次,CC打印15次
  98.  * ......来10轮  
  99.  * @author xialei
  100.  *
  101.  */
  102. public class ThreadOrderAccess
  103. {
  104.   public static void main(String[] args)
  105.   {
  106.      ShareResource sr = new ShareResource();
  107.      
  108.      new Thread(() -> {
  109.        for (int i = 1; i <=10; i++) 
  110.        {
  111.           sr.print5(i);
  112.        }
  113.      }, "AA").start();
  114.      new Thread(() -> {
  115.        for (int i = 1; i <=10; i++) 
  116.        {
  117.           sr.print10(i);
  118.        }
  119.      }, "BB").start();
  120.      new Thread(() -> {
  121.        for (int i = 1; i <=10; i++) 
  122.        {
  123.           sr.print15(i);
  124.        }
  125.      }, "CC").start();   
  126.      
  127.      
  128.   }
  129. }

JUC-线程间通信的更多相关文章

  1. juc包:使用 juc 包下的显式 Lock 实现线程间通信

    一.前置知识 线程间通信三要素: 多线程+判断+操作+通知+资源类. 上面的五个要素,其他三个要素就是普通的多线程程序问题,那么通信就需要线程间的互相通知,往往伴随着何时通信的判断逻辑. 在 java ...

  2. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  3. 线程间通信 GET POST

    线程间通信有三种方法:NSThread   GCD  NSOperation       进程:操作系统里面每一个app就是一个进程. 一个进程里面可以包含多个线程,并且我们每一个app里面有且仅有一 ...

  4. Java多线程编程核心技术---线程间通信(二)

    通过管道进行线程间通信:字节流 Java提供了各种各样的输入/输出流Stream可以很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据,一个线程发送 ...

  5. Java多线程编程核心技术---线程间通信(一)

    线程是操作系统中独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一.线程间通信可以使系统之间的交互性更强大,在大大提高CPU利用率的同时还会使程序员对各 ...

  6. volatile关键字与线程间通信

    >>Java内存模型 现在计算机普遍使用多处理器进行运算,并且为了解决计算机存储设备和处理器的运算速度之间巨大的差距,引入了高速缓存作为缓冲,缓存虽然能极大的提高性能,但是随之带来的缓存一 ...

  7. 06_Java多线程、线程间通信

    1. 线程的概念      1.1多进程与多线程 进程:一个正在执行的程序.每个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个控制单元. 一个进程至少有一个线程. 线程:就是进程中的一个独立 ...

  8. 【原】iOS多线程之线程间通信和线程互斥

    线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...

  9. java多线程系列5-死锁与线程间通信

    这篇文章介绍java死锁机制和线程间通信 死锁 死锁:两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象. 同步代码块的嵌套案例 public class MyLock { // 创建两 ...

  10. Java笔记(二十)……线程间通信

    概述 当需要多线程配合完成一项任务时,往往需要用到线程间通信,以确保任务的稳步快速运行 相关语句 wait():挂起线程,释放锁,相当于自动放弃了执行权限 notify():唤醒wait等待队列里的第 ...

随机推荐

  1. python部署到服务器

    python部署到服务器 linux下的CentOS 7 自带python2.7.5, 使用 python --version 命令查看,因系统需要python2.7.5,因此我们并不卸载,另外安装p ...

  2. cf912D

    题意简述:往n*m的网格中放k条鱼,一个网格最多放一条鱼,然后用一个r*r的网随机去捞鱼,问怎么怎么放鱼能使得捞鱼的期望最大,输出这个期望 题解:肯定优先往中间放,这里k不大,因此有别的简单方法,否则 ...

  3. Qt代码区字符编码转换

    在做通讯练习的时候,发现发送给小助手字符乱码,图片如下 本人Qt Creator是UTF-8,需要改成gbk,代码如下 #include<QTextCodec> // 提供字符编码转换 Q ...

  4. 等差数列,for循环,递归和尾递归的对比

    生活中,如果1+2+3+4.....+100,大家基本上都会用等差数列计算,如果有人从1开始加,不是傻就是白X,那么程序中呢,是不是也是这样.今天无意中看到了尾递归,以前也写过,但是不知道这个专业名词 ...

  5. centos7 lnmp环境搭建

    1- 安装gcc c++编译器 yum install gcc gcc-c++ cmake 2- 安装nginx-1.8.1及依赖包 2.1- 安装nginx依赖包 yum -y install pc ...

  6. P1308 统计单词数(cin,getline() ,transform() )

    题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...

  7. 解决const char* to char* 的错误

    一般情况下 char* string = "abc"; 编译后会出现标题中的错误. 我们只需要在字符串前加上const_cast<char*>即可,这个作用是丢弃变量的 ...

  8. github访问过慢

    转:https://baijiahao.baidu.com/s?id=1608100091125662190&wfr=spider&for=pc https://www.cnblogs ...

  9. Java商城秒杀系统的设计与实战视频教程(SpringBoot版)

    课程目标掌握如何基于Spring Boot构建秒杀系统或者高并发业务系统,以及构建系统时采用的前后端技术栈适用人群Spring Boot实战者,微服务或分布式系统架构实战者,秒杀系统和高并发实战者,中 ...

  10. 获取WEB图片

    public string GetJpgFile(string strFileServerPath ,string strReportDir) { string strPath = "&qu ...