3

オブジェクトを受け取るコールバックがあります。このオブジェクトのコピーを作成し、さらに処理するために別のスレッドに渡す必要があります。コールバックができるだけ早く戻ることが非常に重要です。理想的には、コールバックはコピーをある種のロックフリーコンテナに書き込みます。

コールバックは、単一のスレッドと1つの処理スレッドからのみ呼び出されます。

たくさんのdoubleを他のスレッドに渡すだけでよく、doubleの最大数(約40)がわかります。

何か案は?私はJavaにあまり詳しくないので、スレッド間でデータを渡す通常の方法がわかりません。

4

4 に答える 4

6

これが1回限りのことである場合、つまり40倍程度の倍数を取得し、それを処理する新しいスレッドを開始したい場合は、次のように実行できます。

public void callback(final double[] myDoubles)
{
  new Thread(){
   public void run() {
      // you can use myDoubles here. it will run on a separate thread.
   }}.start()   
};

これが頻繁に発生する場合は、スレッドプールを調べて、 java.utils.concurrent.BlockingQueueを使用する必要があります。名前にもかかわらず、キューはいっぱいになった場合にのみブロックされます。

コールバックメソッドがキューに入れる適切なサイズの2倍の配列を作成できます。put()操作は非常に高速であるため、コールバックメソッドが長時間遅延することはありません。(キューがいっぱいでない限り。)

他のスレッドは、キューでtake()メソッドを使用して、オブジェクトが使用可能になったときにオブジェクトを取得します。take()メソッドは、オブジェクトが使用可能になるまでブロックします。これを望まないが、スレッドを実行し続け、他のことを行う場合は、代わりにpoll()を使用します。

最後に考慮すべきことの1つは、コールバックからのdoubleを処理するワーカースレッドを1つだけにしたいのか、それとも複数必要なのかということです。作業を一度に1つずつ実行する必要がある場合は、スレッドを1つ持つことは理にかなっています。たとえば、配列をファイルに書き込む場合、通常、複数のスレッドでこれを行う意味はありません。Buf各配列で行われる作業が独立している場合は、複数のワーカースレッドを持つのに適しています。

于 2010-05-27T22:21:39.137 に答える
3

「スレッド間で物を渡す」方法については、Javaのスレッドの最も重要な部分は、を実装するクラスのインスタンスであるターゲットjava.lang.Runnableであることに注意してください。Threadインスタンスを渡さずにオブジェクトを作成するRunnable場合、ターゲットはThreadオブジェクト自体です(がjava.lang.Thread実装されているためjava.lang.Runnable)。それ以外の場合は、を実装するカスタムクラスを作成し、Runnableこのクラスのインスタンスを作成して、新しく作成したインスタンスに渡す可能性がありThreadます。この場合、カスタムクラスのインスタンスがターゲットになります。

スレッド(基本的にはRunnableオブジェクト)がオブジェクトにアクセスできるようにすることは、Runnableオブジェクトがインスタンス変数としてオブジェクトへの参照を持っていることを確認しrun、スレッドで実行されているメソッドにオブジェクトをアクセスできるようにすることと同じです。

double配列のコピーを新しく作成されたスレッドに渡す方法の例を次に示します。

class MyRunner implements Runnable
{
    double[] m_data;

    public MyRunner(double[] data)
    {
        this.m_data = data;
    }

    public void run()
    {
        // this code is executed in a thread. It can access `m_data`.
    }
}

public class Callback
{
    public void doCallback(double[] data)
    {
        double[] dataCopy = null;
        if (data != null) {
            dataCopy = new double[data.length];
            System.arraycopy(data, 0, dataCopy, 0, data.length);
        }
        MyRunner target = new MyRunner(dataCopy);
        Thread worker = new Thread(target);
        worker.start();
    }
}
于 2010-05-27T22:08:30.910 に答える
2

doubleの配列で構築されたRunnableの実装を作成し、それをスレッドプールエグゼキュータに渡します。

そのようです:

public class MyDoublesProcessor implements Runnable {
    double[] doublesArray;
    public MyDoublesProcessor(double[] array) {
        doublesArray = array;
    }

    public void run() {
        //do stuff with array
    }
}

Executor exec = Executors.newFixedThreadPool(1);

void callback(double[] array) { //or whatever your callback is
    exec.execute(new MyDoublesProcessor(array));
}
于 2010-05-28T08:38:11.353 に答える
0

新しいスレッドを作成しますか、それとも既存の別のスレッドにアクセスする必要がありますか?

ケース1の場合、スレッドプールから新しいスレッドを要求し、それに情報を渡し、実行するように指示してから戻ることができます。

ケース2では、データを渡すことができる中間スレッドを作成する必要がある場合があります。その後、データを保持し、(たとえば)データ処理スレッドで同期関数を呼び出そうとします。中間スレッドに渡さない場合、他の同期されたスレッドへのデータの受け渡しをブロックする可能性がある期間がわかりません。

スレッドプーリングに関するJavaの要点から:

http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html

newCachedThreadPoolメソッドは、拡張可能なスレッドプールを持つエグゼキュータを作成します。このエグゼキュータは、多くの短期間のタスクを起動するアプリケーションに適しています。

于 2010-05-27T21:38:16.227 に答える