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. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  2. Java多线程:wait(),notify(),notifyAll()

    1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...

  3. Java多线程的wait(),notify(),notifyAll()

    在多线程的情况下.因为多个线程与存储空间共享相同的过程,同时带来的便利.它也带来了访问冲突这个严重的问题. Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问. ...

  4. Java多线程中wait, notify and notifyAll的使用

    本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...

  5. java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态

    刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...

  6. Java多线程Runnable与Callable区别与拓展

    我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...

  7. Java多线程技术-wait/notify/join

    wait/notify的作用 wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到 ...

  8. Java多线程wait和notify协作,按序打印abc

    有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...

  9. java 多线程(wait/notify/notifyall)

    package com.example; public class App { /* wait\notify\notifyAll 都属于object的内置方法 * wait: 持有该对象的线程把该对象 ...

随机推荐

  1. Console-terminal-tty-shell-kernel

    Console-terminal-tty-shell-kernel 1. 先看图表     1.1 简表     1.2 shell与内核的示意图     1.3 Console-terminal-t ...

  2. 基于LAMP实现后台活动发布和前端扫码签到系统

    目的 无论是公司.学校和社会团体,都会举办各式各样的活动,比如运动会.部门会议.项目会议.野炊.团建等.作为团队管理者来讲,当然希望能够把这类活动转移到线上形成完整的系统,类似于电子流的形式.本文以学 ...

  3. [转]SparkSQL – 有必要坐下来聊聊Join

    转载自网易范欣欣http://hbasefly.com Join背景介绍 Join是数据库查询永远绕不开的话题,传统查询SQL技术总体可以分为简单操作(过滤操作-where.排序操作-limit等), ...

  4. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-move

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  5. php5.3不支持 ereg、ereg_replace等函数问题

    在php5.3环境下运行oscommerce,常常会出现Deprecated: Function ereg() is deprecated in...和Deprecated: Function ere ...

  6. Golang的进制转换实战案例

    Golang的进制转换实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常用进制概述 1>.进制概述 进制也就是进位制,是人们规定的一种进位方法.举个例子:二进制就 ...

  7. 微信公众号开发 获取openid时报错40029 invalid code 问题的解决

    {"errcode":40029,"errmsg":"invalid code, hints: [ req_id: aELCyY4ce-WOFLAa ...

  8. 官网英文版学习——RabbitMQ学习笔记(九)总结

    RabbitMQ与spingboot相整合,主要步骤也很简单: 一.首先需要的是添加依赖 二.需要设置属性,属性主要是设置rabbitmq的地址端口,用户名密码回调等需要用到的一些常量,在整合过程中, ...

  9. Liunx用户运行模式

    运行模式也可以称之为运行级别(Running Level). 在linux中存在一个进程:init (initialize,初始化),进程id是1. [he@localhost ~]$ ps -ef ...

  10. python基础笔记:判断与循环

    判断: #根据身高为1.75,体重为65的小明的bmi输出小明的身材 h=1.75 w=65 bmi=w/(h*h) if bmi<18.5: print('过轻') elif bmi<= ...