为了账号安全,请及时绑定邮箱和手机立即绑定

一直wait导致程序无法停止怎么解决?

试图停止线程,在EnergyTransferTask类中加入退出旗标,修改后代码如下:

public class EnergyTransferTask implements Runnable {
    private EnergySystem energySystem;// 共享的能量世界
    private int fromBox;// 能量转移的源能量盒子下标
    private double maxAmount;// 单次能量转移最大单元
    private int DELAY = 10;// 最大休眠时间(毫秒)
    volatile boolean keepRunning = true;
    private int count = 0;
    public EnergyTransferTask(EnergySystem energySystem, int from, double max) {
        this.energySystem = energySystem;
        this.fromBox = from;
        this.maxAmount = max;
    }
    public void run() {
        try {
            while (keepRunning) {
                int toBox = (int) (energySystem.getBoxAmount() * Math.random());
                double amount = maxAmount * Math.random();
                energySystem.transfer(fromBox, toBox, amount);
                Thread.sleep((int) (DELAY * Math.random()));
                count++;
                if(count == 5){
                    keepRunning = false;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

为了便于研究,将盒子数量BOX_AMOUNT改为2,但发现控制台的输出停止后,程序仍无法正常退出。推测是在wait set中线程一直在等待中,而其他线程已经执行完毕无法将其唤醒,有什么好的解决方法吗?

http://img1.sycdn.imooc.com//561a69170001f90106040189.jpg


正在回答

3 回答

没看到你别的代码,也没看这个题目,不知道具体问题, 但是就你出现的那个问题,notify是唤醒线程池中的任意一个线程,当你的读和取都有多个线程时,有使用的同一个锁,确实会造成死锁,

JDK1.5 java.util.concurrent.locks 包中提供了更方便的灵活的解决办法    

java.util.concurrent.locks包下    

Lock接口:代替了同步代码块或者同步函数,将同步的隐式锁操作变为了显示操作,而已可以加上多个监视器,

Condition接口中

signal();唤醒锁上指定监视器的一个线程 代替了notify()方法不会造成死锁   


0 回复 有任何疑惑可以回复我~

十分感谢楼上的同学指明方向,将synchronized同步机制改成ReentrantLock的lock机制,可以解决这个问题。

因此在EnergySystem类中声明:

    private final ReentrantLock lock = new ReentrantLock();  
    private Condition notEnouge = lock.newCondition();  
    private Condition enouge = lock.newCondition();

并将该类中的synchronized块改为:

        lock.lock();  
        try {  
            while (energyBoxes[from] < amount) { 
                notEnouge.await(1, TimeUnit.SECONDS);// wait();  
            }  
            System.out.print(Thread.currentThread().getName());
            energyBoxes[from] -= amount;
            System.out.printf("从%d转移%10.2f单位能量到%d", from, amount, to);
            energyBoxes[to] += amount;
            System.out.printf(" 能量总和:%10.2f%n", getTotalEnergies());
            enouge.signalAll();// notifyAll();
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        } finally {  
            lock.unlock();  
        }

这样,等待中的线程每隔1秒就可重新争取锁,就不会陷入无限等待中。

1 回复 有任何疑惑可以回复我~

发现有人这么说

wait notify 可以被认为是过时的机制,自从concurrent包之后,不要再用 wait notify 了,所以研究的意义可能也不大……要一个线程去等另一个线程,或者等某一个条件达成,concurrent包里有不好工具可以用,方法也不止一种(看情况用哪种),每一种都比 wait notify 好。       

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消

一直wait导致程序无法停止怎么解决?

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信