Java中使用生产者消费者模式实现数字交替输出。使用Integer包装类出异常。
这里用的是老杜的题b站视频
我怀疑是Integer包装类是线程安全的,会导致锁出问题,导致t1线程锁没有了。
希望看到的网友能分析一下原理……
代码
package com.zuoxianzhifeng.study.thread.temp;
/**
* 1、使用生产者和消费者模式实现,交替输出:
* 假设只有两个线程,输出以下结果:
* t1-->1
* t2-->2
* t1-->3
* t2-->4
* t1-->5
* t2-->6
* ....
*
* 要求:必须交替,并且t1线程负责输出奇数。t2线程负责输出偶数。
* 两个线程共享一个数字,每个线程执行时都要对这个数字进行:++
*
*/
public class Homework2 {
public static void main(String[] args) throws InterruptedException {
Integer integer = 1;
//new线程 关联同一个Integer对象
Thread t1 = new Thread(new MyRunnableA(integer));
Thread t2 = new Thread(new MyRunnableB(integer));
//重命名
t1.setName("t1-->");
t2.setName("t2-->");
//执行
t2.start();
t1.start();
}
}
//奇数线程
class MyRunnableA implements Runnable{
//定义共享对象
Integer integer;
public MyRunnableA(Integer integer) {
this.integer = integer;
}
@Override
public void run() {
while (true){
synchronized (integer){
if (integer % 2 == 0){//如果integer现在是偶数
try {
integer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//代码执行到这里 integer是奇数 可以打印输出
System.out.println(Thread.currentThread().getName()+integer);
integer ++;//现在integer是偶数了 严重怀疑这里出问题了
//代码执行到这里 integer是偶数 唤醒偶数线程
integer.notify();
//代码执行到这里 本奇数线程释放锁
}
}
}
}
//偶数线程
class MyRunnableB implements Runnable{
//定义共享对象
Integer integer;
public MyRunnableB(Integer integer) {
this.integer = integer;
}
@Override
public void run() {
while (true){
synchronized (integer){
if (integer % 2 == 1){//如果integer现在是奇数
try {
integer.wait();//偶数线程进入等待 并且释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//代码执行到这里 integer是偶数 可以打印输出
System.out.println(Thread.currentThread().getName()+integer);
integer ++;//现在integer是奇数了 严重怀疑这里出问题了
//代码执行到这里 integer是奇数 唤醒奇数线程
integer.notify();
//代码执行到这里 本偶数线程释放锁
}
}
}
}
/*
t1-->1
Exception in thread "t1-->" java.lang.IllegalMonitorStateException: current thread is not owner
at java.base/java.lang.Object.notify(Native Method)
at com.zuoxianzhifeng.study.thread.temp.MyRunnableA.run(Homework2.java:65)
at java.base/java.lang.Thread.run(Thread.java:832)
*/
我这边自己写了个类
在线程run方法中使用myInteger.i
的方式访问i
实现了想要效果
class MyInteger{
public int i = 1;
}
/*
t1-->27365
t2-->27366
t1-->27367
t2-->27368
t1-->27369
*/