0

並行性を使用する Java 割り当てについて助けが必要です。私が抱えている問題はget方法にありますが、問題は見つかりません。ただし、正しくアクセスされていないか、想定どおりに動作していないように感じます。要約すると、問題は、私がすべての金属を手に入れていることですが、消費者には何も与えていません。追加情報を提供する必要がある場合はお知らせください。

各ブローカーは 3 種類の金属すべての在庫を保持していますが、「専門」と呼ばれるそのうちの 1 つのみの「サプライヤー」です。時々、精錬業者は精錬された金属の出荷を、その供給者であるブローカーに届けます。たとえば、精錬業者が 30 オンスの金を金の供給業者に納入するとします。消費者は定期的にブローカーに注文書を出します。各注文は、各金属のオンス数を指定します。任意のブローカーに配置できます。ブローカーは、可能であれば、自身の在庫から注文を処理します。金属 M の供給業者が十分な量の M を手元に持っていないために注文に応じることができない場合、精錬業者から追加の金属を入手するまで待ちます。しかし、他の金属が不足している場合は、その金属のサプライヤーと取引することでそれを取得しようとします. 話を簡単にするために、やや非現実的ですが、オンスの金、プラチナ、またはウランはすべて等しく価値があります。つまり、3 オンスの金は 3 オンスのウランまたは 3 オンスのプラチナと交換できます。

申し訳ありませんが、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;
}
4

1 に答える 1

1

具体的にget(int[] order)メソッドを見ると、考慮していないことがいくつかあります。質問でマルチスレッドについて言及したので、複数のスレッドがこのメソッドを一度に呼び出すことができると思います。この事実を考えると、共有リソースへの同期アクセスを考慮していませんmetals[]。操作-=はスレッドセーフではなく、その配列に対する反復でもありません。thisまた、同期を追加する場合は、大きなブロックを同期するとパフォーマンスに影響を与える可能性があるため、パフォーマンスに関心がある場合は、同期する対象を最小限に抑えるようにしてください。

編集: また、同期ブロックに wait() がないことをお勧めします (ただし、これは要求しませんでした)。metals[]これにより、同期ブロック内のスレッドが待機中にブロックされるため、デッドロックが発生します。

于 2013-02-14T17:21:29.070 に答える