1

ノードのセットにpingを実行し、文字列のArrayListを将来のオブジェクトに返してファイルに出力する単純なユーティリティがあります。プログラムは、ユーザーが終了するまで実行する必要があります。

future が結果を受け取る (または少なくとも結果をメソッドに渡してファイルに出力する) ようには見えません。同時に実行しているスレッドの数に関係なく (入力ファイルによって決定される常に 100 未満)、最初と最後に初期化されたスレッドからの結果のみを出力しています。

サニティ チェックとして、各スレッドが結果を送信してから閉じて Future オブジェクトに結果を返すグローバル変数を作成しました。この変数は、すべてのスレッドによって正しく更新されます。

Future がスレッドからすべての結果を受け取っていないように見える理由は誰にもありますか?

public class PingUtility{
    public static ExecutorService pool = Executors.newFixedThreadPool(100);
    static Future<ArrayList<String>> future;

    public static void main(String[] args) throws Exception {

        Timer timer = new Timer();
        TimerTask task = new TimerTask(){
            public void run(){
                //Creates a pool of threads to be executed
                ArrayList<String[]> nodes = new ArrayList<String[]>()
                future = pool.submit(new PingNode(nodes));
                }   
            }
        };

        timer.scheduleAtFixedRate(task, 0, interval);

        while(true){
            try{
                ArrayList<String[]> tempOutputArray = future.get();
                Iterator<String[]> it = tempOutputArray.iterator();
                while(it.hasNext()) appendFile(it.next());
                tempOutputArray.clear();
            }catch(Exception nullException){
            //Do nothing
            }
        }
    }
4

2 に答える 2

3

あなたの問題は、タイマータスクスレッドで同期せずfutureに静的フィールドを変更し、メインスレッドでそれを読み取っていることです。変更して読み取るときに同期するか、別のメカニズムを使用してスレッド間で情報を共有する必要があります。

呼び出しからメソッドに情報を送信するより良い方法として、staticフィールドからa に切り替えることをお勧めします。これにより、自分で同期を行う必要がなくなり、複数のタイマー タスクが開始され、コンシューマーがそれらから削除される前に上書きされるという競合状態から保護されます。たぶん次のようなもの:LinkedBlockingQueuePingNodeappendFile(...)futureget()

 BlockingQueue<String[]> queue = new LinkedBlockingQueue<String[]>();
 ...

 // inside of run, producer passes the queue into the PingNode
 public void run() {
     pool.submit(new PingNode(queue));
 }

 // consumer
 while (true) {
     String[] array = queue.take();
     ...
 }

これは、完了時にスレッドを停止する方法には影響しません。タイマー タスクが強制終了された場合、エンティティはメイン ループを停止する終了オブジェクトをキューに追加できます。

于 2013-04-11T13:57:08.333 に答える
0

Future オブジェクトは、ArrayList のようなビンではなく、単一の計算結果を指すだけです。この Future への静的ポインターは 1 つしかないため、次のようなことが起こっていると思います。

    future = null
    nullException
    nullException
    nullException
    nullException
    ...
    First thread finally sets future = Future<ArrayList<String>>
    Call to future.get() blocks...
        Meanwhile, all other threads get scheduled, and they reassign future
        The last thread will obviously get the last say in what future points to
    Data is gathered, written to file, loop continues
    future now points to the Future from the last thread
    Results from last thread get printed
于 2013-04-11T14:02:43.603 に答える