#独家
多线程wait方法报错?

2023-07-02 0 1,326

我的问题:三个线程的ID分别是A,B,C;,每个线程将自己的ID值在屏幕上打印5遍,打印顺序是ABCABC。
我编写的代码:

package 并发编程.work2;

public class Test {
    private static volatile String CURRENT_THREAD = "A";

    public static void main(String[] args) {
        Thread t1 = new Thread(new PrintThreadName(), "A");
        Thread t2 = new Thread(new PrintThreadName(), "B");
        Thread t3 = new Thread(new PrintThreadName(), "C");
        t1.start();
        t2.start();
        t3.start();
    }

    static class PrintThreadName implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                synchronized (CURRENT_THREAD) {
                    // 从A开始
                    while (!CURRENT_THREAD.equals(Thread.currentThread().getName())) {
                        try {
                            CURRENT_THREAD.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(CURRENT_THREAD);
                    // 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程
                    if (CURRENT_THREAD.equals("A")) {
                        CURRENT_THREAD = "B";
                    } else if (CURRENT_THREAD.equals("B")) {
                        CURRENT_THREAD = "C";
                    } else if (CURRENT_THREAD.equals("C")) {
                        CURRENT_THREAD = "A";
                    }
                    CURRENT_THREAD.notifyAll();
                }
            }
        }
    }
}

但是出现了错误

主要的问题是:

// 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程
if (CURRENT_THREAD.equals("A")) {
    CURRENT_THREAD = "B";
} else if (CURRENT_THREAD.equals("B")) {
    CURRENT_THREAD = "C";
} else if (CURRENT_THREAD.equals("C")) {
    CURRENT_THREAD = "A";
}

你使用一个volatile修饰的字符串CURRENT_THREAD来充当锁的角色
但是却在锁对象释放自己拥有的锁之前就把锁的引用给修改了
也就会出现 现在的锁对象其实已经被修改了(它是没有锁的 锁在之前的对象身上)
你还要让它释放锁 属于是强人所难了 所以会报错
这个错误产生的原因是某一线程在等待其他线程释放锁 但是突然要求它释放锁 它还在等呢怎么会有锁 所以就会抛出IllegalMonitorStateException
解决方法就是额外使用另一个锁对象来实现同步 不要在锁对象释放锁之前对它进行任何修改 可以参照楼上的方案

package 并发编程.work2;

public class Test {
    private static final Object lock = new Object();
    private static volatile String CURRENT_THREAD = "A";

    public static void main(String[] args) {
        Thread t1 = new Thread(new PrintThreadName(), "A");
        Thread t2 = new Thread(new PrintThreadName(), "B");
        Thread t3 = new Thread(new PrintThreadName(), "C");
        t1.start();
        t2.start();
        t3.start();
    }

    static class PrintThreadName implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                synchronized (lock) {
                    // 从A开始
                    while (!CURRENT_THREAD.equals(Thread.currentThread().getName())) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(CURRENT_THREAD);
                    // 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程
                    if (CURRENT_THREAD.equals("A")) {
                        CURRENT_THREAD = "B";
                    } else if (CURRENT_THREAD.equals("B")) {
                        CURRENT_THREAD = "C";
                    } else if (CURRENT_THREAD.equals("C")) {
                        CURRENT_THREAD = "A";
                    }
                    lock.notifyAll();
                }
            }
        }
    }
}
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

1. JK下载官网所有资源来源于开发团队,加入会员即可下载使用!如有问题请联系右下角在线客服!
2. JK下载官方保障所有软件都通过人工亲测,为每位会员用户提供安全可靠的应用软件、游戏资源下载及程序开发服务。
3. JK开发团队针对会员诉求,历经多年拥有现今开发成果, 每款应用程序上线前都经过人工测试无误后提供安装使用,只为会员提供安全原创的应用。
4. PC/移动端应用下载后如遇安装使用问题请联系右下角在线客服或提交工单,一对一指导解决疑难。

JK软件下载官网 技术分享 多线程wait方法报错? https://www.jkxiazai.com/1904.html

JK软件应用商店是经过官方安全认证,保障正版软件平台

相关资源

官方客服团队

为您解决烦忧 - 24小时在线 专业服务