java并发,生产者(经纪人)和消费者

时间:2013-02-14 16:43:47

标签: java multithreading concurrency

我需要有关使用并发的java分配的帮助。我遇到的问题是get方法,我找不到任何问题。但是,感觉它没有被正确访问,或者它没有按照预期进行操作。总而言之,问题在于我得到了所有的金属,但我没有给消费者任何东西,我不知道这是怎么回事。如果我需要提供任何其他信息,请告诉我。

每个经纪商都拥有所有三种金属的库存,但只是其中一种金属的“供应商”,被称为“专业”。炼油厂不时会向作为供应商的经纪人提供一批精炼金属。例如,炼油厂可能会向黄金供应商交付30盎司的黄金。消费者定期向经纪人下订单。每个订单都指定每种金属的盎司数。它可以与任何经纪人一起放置。如果可能,经纪人将从自己的股票中填写订单。如果金属M的供应商无法填写订单,因为它手头没有足够的M,它只是等待它从炼油厂获得更多。但如果它是一些其他金属的短缺,它试图通过与该金属的供应商进行交易来获得它。为了简单起见,我们会假设,有些不切实际,盎司的黄金,铂金或铀都同样有价值。也就是说,三盎司的黄金可以换成三盎司的铀或三盎司的铂金。

抱歉,我无法显示使用BrokerImplementation的类。我不能,因为它们都是.class文件,并且不认为上传位代码会有任何帮助。

提前感谢您提供的任何帮助。

// This class overrides all it's methods from the Broker interface
public class BrokerImplementation implements Broker, IBM {

int specialty;
int[] metals = {0, 0, 0};

/**
 * The constructor takes a single integer parameter, the code for the metal
 * which this broker supplies.
 *
 * @param specialty
 */
public BrokerImplementation(int specialty) {
    this.specialty = specialty;
}

/**
 * This method is used by Project2.main to audit the global state when the
 * system shuts down. The Broker should fill in result with the amount of
 * each metal it has on hand. 
 *
 * @param result
 */
@Override
public void getAmountOnHand(int[] result) {

    //GOLD, PLATINUM, URANIUM are are constants in the IBM interface
    //which correspond to the indexes {0, 1, 2} 
    result[GOLD] = metals[GOLD];
    result[PLATINUM] = metals[PLATINUM];
    result[URANIUM] = metals[URANIUM];
}

/**
 * A consumer calls this method to place an order. The argument is a
 * three-element array indicating the number of ounces of gold, platinum,
 * and uranium desired. It should return only when the order has been
 * filled.
 *
 * @param metals
 */
@Override
public void get(int[] order) {

    for(int i = 0; i < 3; i++){
    if (metals[i] > order[i]) {
        metals[i] -= order[i];
    } else {
        this.swap(i, order[i] - metals[i]);
        this.get(order);
        try {
            wait();
        } catch (InterruptedException ex) {
            Logger.getLogger(BrokerImplementation.class.getName()).log(Level.SEVERE, null, ex);
        }
        notifyAll();
    }
    }
}

/**
 * Another broker calls this method to swap one metal for another. The what
 * argument indicates one of the metals; the other one is the metal in which
 * this broker specializes. The ounces argument indicates how many ounces to
 * swap.
 *
 * @param what
 * @param ounces
 */
@Override
public void swap(int what, int ounces) {

    synchronized (this) {
        if (metals[specialty] >= ounces) {

            metals[specialty] -= ounces;
            metals[what] += ounces;

        } else {
            notifyAll();
            try {
                wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(BrokerImplementation.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }
}

/**
 * The refiner calls this method to deliver a load of metal to the broker.
 * The argument ounces is a number of ounces. The metal is the one this
 * broker supplies.
 *
 * @param ounces
 */
@Override
public void deliver(final int ounces) {
    System.out.println("available " + metals[specialty]);
    metals[specialty] += ounces;
}

1 个答案:

答案 0 :(得分:1)

专门研究get(int[] order)方法,有几件事你没有考虑过。由于您在问题中提到多线程,我假设多个线程可以同时调用此方法。鉴于此事实,您尚未考虑对共享资源metals[]的同步访问。操作-=不是线程安全的,也不是你对该数组的迭代。此外,当您添加同步时,如果您关注性能,请尝试最小化同步内容,因为同步this上的大块可能会对性能产生影响。

编辑:我还建议(尽管你没有要求这样做)你的同步块中没有wait()。这将导致死锁,因为同步块中的线程将在等待时阻塞metals[]