1

5 ~ 10 の同時実行スレッドの間で実行されるマルチスレッド バッチ処理アプリがあります。それらのデータ セグメントは、可能な限り均等に分散されるように慎重にスライスされますが、もちろん、実行時間は常に異なります。私がやりたいことは、最後のスレッドが終了したときに最後の種類の onFinalize メソッドを呼び出すことです。これにより、いくつかの統計計算が行われます。

スレッドが最後のスレッドであることを知る最善の方法は (一種の歩行者のように見える DB をクエリするのではなく)、新しいスレッドが実行されたときに同期ブロックでインクリメントされる静的 var を持つことかどうか疑問に思っていました。各スレッドの終了時に加算および減算されます。そのため、スレッドが終了してデクリメントを行うときに、未処理のスレッド数が 0 であるかどうかを if で確認し、最終的な統計を呼び出すことができます。

それが私が考えていたことです。これを達成するための、より優れた、よりエレガントな、または防弾の方法があるかどうか疑問に思っていました。

Java 7 の使用

ありがとう

4

4 に答える 4

0

最後に各スレッドでThread.join()を呼び出さないのはなぜですか?forループを使用して、それぞれで呼び出すことができます。最初の実行でロックされ、それが完了すると、戻って次の実行でロックされます。ループを終了すると、それらはすべて終了しました。

public class ThreadManager {
    private List<Thread> threads;

    public void addThread(Thread thread) {
        threads.add(thread);
    }

    public void waitTillAllComplete() {
        for (int ind=0; ind<threads.size(); ind++)
            threads.get(ind).join();
    }
}
于 2012-09-05T05:17:02.833 に答える
0

Runnableより堅牢なスレッド アーキテクチャを提供するために、基本的なインターフェイスを拡張するフレームワークを作成することで、同様のことを行いました。後で、これが GWT の非同期コードと同様の目的で驚くほど似ていることを発見しました。

これは記憶によるものですが、基本的には次のようになります。

public interface AsyncRunnable<T> extends Runnable
{
    AsyncCallback<T> getCallback();

    T runAsync();
}

public interface AsyncCallback<T>
{
    void onSuccess(T data);
    void onFailure(Exception exception);
}

public interface AsyncCallbackInvoker<T> extends Runnable
{
    // implies requirement for callback...
    AsyncCallback<T> getCallback();
}

public class SuccessfulAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
    private final AsyncCallback<T> callback;
    private final T data;

    public SuccessfulAsyncCallbackInvoker(AsyncCallback<T> callback, T data)
    {
        // note: data being null may be valid; callback would not be

        this.callback = callback;
        this.data = data;
    }

    @Override
    public void run()
    {
        callback.onSuccess(data);
    }

    @Override
    public AsyncCallback<T> getCallback()
    {
        return callback;
    }
}

public class FailureAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
    private final AsyncCallback<T> callback;
    private final Exception  exception;

    public FailureAsyncCallbackInvoker(AsyncCallback<T> callback, Exception exception)
    {
        // note: data being null may be valid; callback would not be

        this.callback = callback;
        this.exception= exception;
    }

    @Override
    public void run()
    {
        callback.onFailure(exception);
    }

    @Override
    public AsyncCallback<T> getCallback()
    {
        return callback;
    }
}

public abstract class AbstractAsyncRunnable<T> implements AsyncRunnable<T>
{
    private final AsyncCallback<T> callback;

    public AbstractAsyncRunnable(AsyncCallback<T> callback)
    {
        // if == null -> throw

        this.callback = callback;
    }

    @Override
    public /* final */ void run()
    {
        AsyncCallbackInvoker<T> invoker;

        try
        {
            T data = runAsync();

            invoker = new SuccessfulAsyncCallbackInvoker<T>(callback, data);
        }
        catch (Exception e)
        {
            invoker = new FailureAsyncCallbackInvoker<T>(callback, e);
        }

        invokeCallback(invoker);
    }

    // allows overriding to put callback on whatever Thread you want
    protected void invokeCallback(AsyncCallbackInvoker<T> invoker)
    {
        invoker.run();
    }
}

実際には、それは信じられないほど堅牢であることが証明されており、特にオーバーライド機能を提供することで、invokeCallback応答が保証された多くのスレッドセーフ操作を活用できるようになりました。

runAsync実際には、実装はメソッドをオーバーライドして、適切と思われるAsyncRunnableものを提供するだけで済みますAsyncCallback。単純に完了をマークする手段として実際に使用する場合があり、そのような場合TVoid(使用する場合はreturn nullfrom runAsync) になる可能性があることに注意することが重要です。

于 2012-09-05T05:32:22.910 に答える
0

他にできることは、ThreadManagerクラスを作成することです。このクラスにはList<Thread>. Threadタスクを実行するために新しいを作成するときはいつでもregisterThreadManager. 次にThreadManager、 の合計を返すnumberinlive Threadsメソッドを作成しますList

このようにして、実行中のスレッドの数をいつでも確認でき、必要に応じて実行中のスレッドに対して他の操作を実行することもできます。また、Thread定期的にもう 1 つ実行する必要があります。これにより、List.

サンプルThreadManagerは次のようになります。

public class ThreadManager {
    private static ThreadManager tm;
    private List<Thread> threads;

    public static ThreadManager get() {
        if(null == tm) {
            tm = new ThreadManager();
        }

        return tm;
    }

    private ThreadManager() {
        threads = new ArrayList<Thread>();
    }

    public int getCountOfAliveThreads() {
        int count = 0;
        for(Thread t : threads) {
            if(t.isAlive()) {
                count++;
            }
        }

        return count;
    }
}

お役に立てれば。で他の機能も実行できますThread List

于 2012-09-05T05:34:55.170 に答える
-1

すべての非常に便利で啓発的な回答に感謝しますが、 static と volatile を使用した単純なカウンターは正常に機能するようです:

private static volatile int crntThrdCnt = 0;

その後

    @Override
public void run() 
{
    crntThrdCnt++;
    this.runBatchInstance();
    crntThrdCnt--;

    if(crntThrdCnt == 0)
    {
        ProcessManager prcsMgr = new ProcessManager();
        Batch batch = prcsMgr.getBatch(this.batchID);
        batch.setEndTime(new Date());
        prcsMgr.updateBatch(batch);
    }
}
于 2012-09-05T05:43:14.493 に答える