Java多线程通讯---------wait,notify区别
class Res{
public String username;
public String sex;
}
class Out extends Thread{
Res res;
public Out(Res res){
this.res=res;
}
@Override
public void run() {
//写操作
int count=0;
while (true){
// synchronized (res.getClass()){
if(count==0){//偶数
res.username="小明";
res.sex="男";
} else {//奇数
res.username="小红";
res.sex="女";
}
count=(count+1)%2;
// }
}
}
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
}
@Override
public void run() {
while (true){
// synchronized (res.getClass()){
System.out.println(res.username+","+res.sex);
// }
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
}
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
出现以上结果??消费者一直消费或者生产者一直生产
解决方法:生产者生产完成后消费者方可消费,否者不可消费,消费者未消费或者未消费完生产者不可生产,一次生产一次消费。其实也就是保证对res共享资源的操作同一时刻仅有同一个线程进行操作,
wait、notify、notifyAll方法
wait、notify、notifyAll是三个定义在Object类里的方法,可以用来控制线程的状态。
这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。当前线程从运行变为阻塞,释放所的资源
如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。让持有该锁的线程从阻塞态变为就绪。
如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
注意:一定要在线程同步中使用,并且是同一个锁的资源
通过以下方式即可完成需求。
生产者获取res.getClass锁后,如果flag为true生产者通过调用res.getClass.wait进行等待,此时其他线程可获取该锁,如果flag为false,进行生产,然后设置flag为true保证资源消费后方可再生产,接着通过notify通知其他唤醒其他线程。
class Res{
public String username;
public String sex;
//true 生产者等待,消费者可消费 false生产者可以生产,消费者不可消费
public boolean flag=false;
}
class Out extends Thread{
Res res;
public Out(Res res){
this.res=res;
}
@Override
public void run() {
//写操作
int count=0;
while (true){
synchronized (res.getClass()){
if(res.flag){
try {
res.getClass().wait();//让当前线程从运行变为阻塞,并且释放所的资源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count==0){//偶数
res.username="小明";
res.sex="男";
} else {//奇数
res.username="小红";
res.sex="女";
}
count=(count+1)%2;
res.flag=true;
res.getClass().notify();
}
}
}
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
}
@Override
public void run() {
while (true){
synchronized (res.getClass()){
if(!res.flag){
try {
res.getClass().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.username+","+res.sex);
res.flag=false;
res.getClass().notify();
}
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
}
输出如下:
小明,男
小红,女
小明,男
小红,女
小明,男
小红,女
小明,男
小红,女
如果去掉notify会怎样?去掉一个?去掉两个?
去掉一个生产者可以打印多个(但是也不多),去掉消费者仅可打印一个,去掉两个可能不打印,也可能打印1个,所以wait、notify必须成对使用
wait(用于同步中)与sleep区别?
都是做休眠,wait需要notify
对于sleep方法,我们首先要知道该方法是属于Thread类中的。而wait方法,则是属于Object类中的。
sleep方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep方法的过程中,线程不会释放对象锁。
而当调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
Java多线程通讯---------wait,notify区别的更多相关文章
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- Java多线程:wait(),notify(),notifyAll()
1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...
- Java多线程的wait(),notify(),notifyAll()
在多线程的情况下.因为多个线程与存储空间共享相同的过程,同时带来的便利.它也带来了访问冲突这个严重的问题. Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问. ...
- Java多线程中wait, notify and notifyAll的使用
本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...
- java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态
刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...
- Java多线程Runnable与Callable区别与拓展
我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...
- Java多线程技术-wait/notify/join
wait/notify的作用 wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到 ...
- Java多线程wait和notify协作,按序打印abc
有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...
- java 多线程(wait/notify/notifyall)
package com.example; public class App { /* wait\notify\notifyAll 都属于object的内置方法 * wait: 持有该对象的线程把该对象 ...
随机推荐
- redheat7 sd 0:0:0:0: [sda] Assuming drive cache: write through(未解决)
以下是我上网查找的解决办法 1. sd 0:0:0:0: [sda] Assuming drive cache: write through 解决方法:/etc/default/grub 文件里去掉 ...
- define可变参数,float数据传输
define可变参数 一般在调试打印Debug信息的时候, 需要可变参数的宏. 从C99开始可以使编译器标准支持可变参数宏(variadic macros), 另外GCC也支持可变参数宏, 但是两种在 ...
- 使用gulp 进行ES6开发
使用gulp 进行ES6开发 一.新建项目 项目结构如下: /app -- /js -- /css /dist -- /js -- /css -- index.html gulpfile.js 我们的 ...
- JDK8~JDK11的新特性
#JDK 1.8 新特性接口中的静态方法 只能由接口自己调用 接口中的默认方法 可以不被覆盖 #JDK 1.9 新特性(可能在JDK8中被忽略了,没来得及加)接口可以定义私有方法,但是只能让自己调用, ...
- 剑指offer第12题打印从1到n位数以及大整数加法乘法
字符和数字加减就是字符的ASCII码和数字直接加减. 方法一: 1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了:如果确实是最后 ...
- Job for nginx.service failed because the control process exited with error code. See “systemctl stat
启动nginx服务时如果遇到这个错误 Job for nginx.service failed because the control process exited with error code. ...
- 读取多张MNIST图片与利用BaseEstimator基类创建分类器
读取多张MNIST图片 在读取多张MNIST图片之前,我们先来看下读取单张图片如何实现 每张数字图片大小都为28 * 28的,需要将数据reshape成28 * 28的,采用最近邻插值,如下 def ...
- LeetCode160 相交链表(双指针)
题目: click here!!题目传送门 思路: 1.笨方法 因为如果两个链表相交的话,从相交的地方往后是同一条链表,所以: 分别遍历两个链表,得出两个链表的长度,两个长度做差得到n,然后将长的链表 ...
- bzoj 1962: 模型王子
呵呵呵呵http://wenku.baidu.com/link?url=o0CPVzuBDLJMt0_7Qph1T7TtdFOzu7O-apIpvaWbIYMz8ZWqBneGqI8LGtLdqpuK ...
- 云时代架构阅读笔记二——Java性能优化(二)
承接上文Java性能优化(一)https://www.cnblogs.com/guo-xu/p/11019267.html 4)尽量确定StringBuffer的容量 在说和这个标题相关之前,先说一下 ...