我来回答一波。

你可以先将 Thread2 的代码做以下两种修改,一种是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

另外一种是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

Thread.yield();

}

}

}

这两种改法你分别运行一下,会发现第一种改法运行以后能得到你想要的结果。

而第二种改法,答案是不一定,并且最终极大可能还是会把两个线程堵死。

你的代码的运行结果跟你的预期不符,主要你忽视了两点:

CPU时间片

wait被notify后,不会立即获得锁。

Java 的对象锁的实现采用的是Monitor机制,具体机制如下,你也可以参考我写过的一篇文章:

当一个线程需要获取 Object 的锁时,会被放入 EntrySet 中进行等待,如果该线程获取到了锁,成为当前锁的 owner。如果根据程序逻辑,一个已经获得了锁的线程缺少某些外部条件,而无法继续进行下去(例如生产者发现队列已满或者消费者发现队列为空),那么该线程可以通过调用 wait 方法将锁释放,进入 wait set 中阻塞进行等待,其它线程在这个时候有机会获得锁,去干其它的事情,从而使得之前不成立的外部条件成立,这样先前被阻塞的线程就可以重新进入 EntrySet 去竞争锁。

你的Thread2调完notify后,Thread1等到Thread2释放锁以后,它还得和 Thread2 站在同一条起跑线上去竞争锁,所以没有绝对地说Thread2释放锁以后,Thread1一定就轮到它获得锁。

你的代码每次都运行相同的结果,原因主要在于 Thread2 会比 Thread1 更容易重新获得锁,因为Thread2的CPU时间片极大可能还没用完。

我们上面的修改,第一种修改是让 Thread2 sleep 一秒,这绝对能让Thread1 有充足的时间获取锁,所以运行结果会如你所预期。

第二种修改是让 Thread2 让出 CPU 时间片,但是同样,CPU 在重新选择线程运行的时候,至少会有一半的机会还是会选中 Thread2。

以上。希望能帮到你。

java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了相关推荐

  1. Java两个线程交替打印奇偶数(两种方法对比)

    简介 本文将承接文章<Java多线程wait()和notify()系列方法使用教程>,我们将通过"两个线程交替打印100内的奇偶数",来展示下wait()方法和noti ...

  2. Java 两线程交替打印奇偶数(一)

    使用synchronized 及 Object对象的wait()和notifyAll()方法, Code如下 package com.shiwei.thread;public class OddEve ...

  3. lock交替打印_面试题Synchronized实现两个线程交替打印

    线程之间的通信有很多种方式,使用Synchronized实现两个线程的交替打印,主要是利用Object对象的wait.notify方法,下面来看下代码: 解释一下上面的程序,首先定义一个内部类,实现s ...

  4. java多线程交替打印_java实现多线程交替打印

    本文实例为大家分享了java实现多线程交替打印的具体代码,供大家参考,具体内容如下 notify+wait实现 import org.junit.Test; import java.util.conc ...

  5. java同时启动多个 无法打印_java实现多线程交替打印两个数

    本文实例为大家分享了java实现多线程交替打印两个数的具体代码,供大家参考,具体内容如下 方法1.使用wait和notify package com.thread; public class T01 ...

  6. Java多线程(2)--Thread类继承和Runnable接口创建线程

    Java语言的JVM允许程序运行多个线程,它通过java.lang.Thread类来体现. Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的,经常把run() ...

  7. Java常见的面试算法题:实现两个线程交替打印1到100的数

    Java常见的面试算法题:实现两个线程交替打印1到100的数 思路: 这是涉及到多个线程打印的问题,一定会用到锁的(synchronized),故这就是一个多线程打印的典型案例. 代码实现: pack ...

  8. java实现123n_java三线程交替打印123……n

    使用多线程交替打印1--n,a进程打印1,4,7,--(3n+1),b进程打印2,7,10,--(3n+2),c进程打印3,6,9,--(3n) 涉及到多线程的同步,阻塞,wait,notify 代码 ...

  9. java实现数组的奇偶数互换

    java实现数组的奇偶数互换 算法需求 算法思路 代码实现 算法需求 定义一个数组变量,将其中的元素进行调换,奇数放到数组左边,偶数放到数组右边 算法思路 偶数放右边,奇数放左边,可以先for遍历数组 ...

最新文章

  1. 第11章 假如没有编程 《丰富多彩的编程世界》
  2. oracle建表权限问题和JSP连接oracle数据库基本操作
  3. 你知道iPhone与摩托车不相容原理么?打脸苹果官方那种
  4. 图说数据中心新风节能技术
  5. python 下载公众号文章_python3下载公众号历史文章
  6. Android 4.0 SDK下载安装
  7. 全国计算机等级考试题库二级C操作题100套(第22套)
  8. 大工17秋《计算机文化基础》在线测试1,大工17秋《组织行为学》在线测试1答案...
  9. cpu序列号唯一吗_怎么看电脑硬件是不是新的 有什么软件能检测吗?
  10. 上海职称英语计算机取消,小编简析2017年职称英语考试是否取消
  11. 解决 error: command 'swig' failed with exit status 1
  12. 选择Windows CE wince嵌入式操作系统 的十大理由
  13. 仅用1天,为湖北黄冈中学搭建直播课堂!
  14. C语言 __DATE__ - C语言零基础入门教程
  15. Java并发编程之并发容器ConcurrentHashMap(JDK1.7)解析
  16. python123测验4程序题_Python面试题245道(从基础到高级)123~141——网络编程,Web—Flask...
  17. java freemark 使用_freemarker单独使用介绍
  18. STL源码剖析-vector
  19. WINDOWS下线程同步探讨
  20. OSI模型第一层物理层

热门文章

  1. Linux应用--日志定时清理
  2. 详解Java反射机制
  3. TensorFlow从1到2(四)时尚单品识别和保存、恢复训练数据
  4. css实现浏览历史小块
  5. 循序渐进学习Linux--第二天更新
  6. include *.h 和 declare class *; 的区别?
  7. jQuery对select操作(2)
  8. 关于ORM中只有XML没有映射实体的思考?期待大家的建议
  9. jQuery学习笔记--目录
  10. java scanner类int_Java之 Scanner类