1

私は3つのクラスを持っています.1つはURLの山を表すことを意図しています

    private Queue<String> queue = new LinkedList<String>();

    public Queue<String> getQueue() {
        return queue;
    }

    private int limit = 5;
    private int stillParsing;

    public synchronized String getNextString() throws InterruptedException {
        while (queue.isEmpty()||stillParsing > limit) {
            System.out.println("no for you "+ queue.peek());
            wait();
        }

        System.out.println("grabbed");

        notify();
        stillParsing++;
        System.out.println(queue.peek());
        return queue.remove();

    }

    public synchronized void doneParsing() {
        stillParsing--;
    }

}

run メソッドが

public void run(){
        try {
        sleep(30);
        for(;;){

              String currenturl = pile.getNextString();
              //(do things)
        }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            pile.doneParsing();
        }
    }

そして、このスニペットを使用して実際にオブジェクトを URL の山に追加するマッパー

while (urls.hasMoreTokens()) {
                try{

                    word.set(urls.nextToken());
                String currenturl = word.toString();
                System.out.println(currenturl);
                pile.getQueue().add(currenturl);

デバッグから、マッパーがキューにデータを入力する前に、すべてのスレッドが一度にキューから取得しようとし、待機状態になると思います。残念ながら、待機中のすべてのスレッドが原因で、プログラムがハングアップし、キューに URL が追加されません。この問題に対処するにはどうすればよいですか?できれば、まだ待機通知を使用している間。

4

2 に答える 2

4
while (urls.hasMoreTokens()) {
    try {
       word.set(urls.nextToken());
       String currenturl = word.toString();
       System.out.println(currenturl);
       pile.getQueue().add(currenturl);

上記のコードでは、パイルのメソッドを経由せずにキューに何かを追加することで、パイルのカプセル化を解除しています。getQueue()このクラスにはメソッドを含めないでください。この共有データ構造へのすべてのアクセスは、同じロックで同期する必要があります。したがって、URL をキューに追加できる同期メソッドを追加する必要があります。また、このメソッドはnotify()(またはより良い: notifyAll()) を呼び出して、何らかの要素がキューに入るのを待っているスレッドをウェイクアップする必要があります。

public synchronized void addUrl(String url) {
    queue.add(url);
    notifyAll();
}
于 2013-07-09T20:26:47.850 に答える
1

コードと説明のすべての行を読まなくても、待機と通知の使用法にはバグがあると言えます。

メソッドwait()がブロックされています。notify()同じモニター上で呼び出された場合にのみ終了します。これは、同じスレッドから と の両方wait()を配置できないことを意味します。永久にブロックされているため、notify()あなたは決して到着しません。notify()wait()

wait():の他のバージョンwait(timeout)はブロックされていますが、指定されたタイムアウトによって制限されています。synchronizedさらに、待機/通知のペアは、ブロックに書き込まれている場合にのみ機能します。

// thread-1
synchronoized(obj) {
    obj.wait();
} 


// thread-2
synchronoized(obj) {
    obj.notify();
} 

スレッド 2 が通知を呼び出すと、スレッド 1 は待機を終了します。

于 2013-07-09T20:26:11.487 に答える