为什么我的线程输出显示两次相同的消息?

时间:2015-02-18 01:56:06

标签: java multithreading

所以我正在上课。该计划的目的是让一些人从袋子里吃水果。水果给予能量,人的能量每秒都在减少。我遇到的问题是,每次吃水果,我都会做一个看起来像这样的输出:

System.out.println("There are now " + fruitList.size() + " fruits left in the bag.");

据我所知,这应该输出我的arraylist的当前大小。令我困惑的是,如果两个人(通过两个不同的线程初始化)大约在同一时间进食,这应该首先显示,“现在袋子里还剩下10个水果。”,然后“那里现在已经把9个水果留在了包里。“问题是这两条消息都会显示有10个结果。

这是Person类中负责此操作的方法:

public void eat(Fruit fruit, ArrayList<Fruit> fruitList, MagicBag magicBag) {
    lock.lock();
    try {
        while (getEnergy() > 20) {
            newDeposit.await();
        }
        if(energy < 30 && energy > 20) {
            System.out.println(this.getName() + " is getting hungry.");
        } else {
        System.out.println(this.getName() + " picked a " + fruitList.get(fruitList.size() - 1).getName() + " and started to eat...");
        Thread.sleep(1000);
        int fruitEnergy;
        fruitEnergy = fruitList.get(fruitList.size() - 1).getEnergyValue();
        fruitList.remove(fruitList.size() - 1);
        if(energy > 100) {
            energy = 100;
        } else {
            energy += fruitEnergy;
        }
        System.out.println(this.getName() + " ate a " + fruitList.get(fruitList.size() - 1).getName() + "!");
        System.out.println("There are now " + fruitList.size() + " fruits left in the bag.");
        magicBag.addFruitsToBag(fruitList, fruit);
        newDeposit.signalAll();
        }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
}

这就是run()在实现运行上述代码的Runnable的类中所做的事情:

public void run() {
    // TODO Auto-generated method stub
    try {
        while(running) {
            if(fruitList.size() > 0) {
            person.eat(fruit, fruitList, magicBag);
            Thread.sleep(1000);
            }
            else {
                kill();
            }
        }
    } catch(InterruptedException e) {
        e.printStackTrace();
    } catch(IndexOutOfBoundsException ie) {
        running = false;
    } catch(NullPointerException ne) {
        ne.printStackTrace();
    }
}

所以,如果有人能帮助我那将是非常棒的。如果您还需要其他任何东西,请询问。

1 个答案:

答案 0 :(得分:3)

fruitList上没有内存障碍,因此您的线程同时检查和修改同一个对象。您需要在fruitList上进行同步(在这种情况下最好,因为这是共享的资源)或使用其他一些机制来确保存在内存障碍,例如使用并发集合。