1

いくつかのスレッドを使用する Java アプリケーションを作成しています。メインメソッドは次のようになります。

WorkerThread[] thread = new WorkerThread();
for (int i = 0 ; i<10 ; i++) {
    thread = new WorkerThread();
    thread.doStuff();
}

私の WorkerThread は次のようになります。

class WorkerThread {
    public void run() {
        ...
    }

    public void doStuff() {
        ...
    }
}

問題は、明らかに、run メソッドから doStuff を呼び出すことです。これは、他のスレッドと並行して実行されますが、メインから直接 doStuff を呼び出すと、並行して実行されません。

わかりました、ここで質問です: run メソッドからではなく、メインから呼び出す doStuff メソッドを同時に実行する方法はありますか?

4

4 に答える 4

2

Thread オブジェクトのメソッドを直接呼び出すことはできません。Thread で同時実行性を取得する唯一の方法は、その start() メソッドを呼び出すことです。このメソッドは、別の実行スレッドで run() を呼び出します。main() から他のメソッドを直接呼び出すことは、通常の非 Thread オブジェクトでメソッドを呼び出すことと同じです。同時実行性はなく、特別なことは何も起こらず、メソッドはすぐに実行されます。

メインスレッドとワーカースレッドの間で通信しようとしているようです。各スレッドの run() メソッドは、そのスレッドでのコードの実行を担当します。その run() メソッドと通信できる場合は、そのスレッドで何が起こるかを制御できます。

これを行う 1 つの方法は、スレッドを構築するときに変数を渡すことです。run() メソッドが何をすべきかを判断するために調べることができる値を保存します。たとえば、以下の列挙型には 3 つの可能なアクションがあります。run() メソッドは列挙型を見て、WorkerThread() コンストラクターに渡された値に基づいて何をすべきかを決定します。

class WorkerThread {
    public enum Action { DO_STUFF, MAKE_WIDGETS, FROB_BARS }
    private Action action;

    public WorkerThread(Action action) {
        this.action = action;
    }

    public void run (){
        switch (action) {
            case DO_STUFF:     doStuff();     break;
            case MAKE_WIDGETS: makeWidgets(); break;
            case FROB_BARS:    frobBars();    break;
        }
    }

    public void doStuff()     { ... }
    public void makeWidgets() { ... }
    public void frobBars()    { ... }
}

main() メソッドは次のようになります。実行するアクションを渡す WorkerThreads を作成してから、start() を呼び出します。

WorkerThread[] threads = new WorkerThread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new WorkerThread(WorkerThread.Action.DO_STUFF);
    threads[i].start();
}

同じことを無数の異なる方法で行うことができます。WorkerThread クラスを 1 つ持つ代わりに、異なる run() メソッドを持ついくつかの異なるクラスを持ち、main() から適切なサブクラスをインスタンス化することができます。

class DoStuffWorkerThread     extends Thread { ... }
class MakeWidgetsWorkerThread extends Thread { ... }
class FrobBarsWorkerThread    extends Thread { ... }

必要に応じて、main() 内で匿名の Thread クラスを作成することもできます。次に、ロジックは main() が望むものであれば何でもかまいません。

Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new Thread() {
        public void run() {
            doStuff();
        }
    };

    threads[i].start();
}
于 2012-12-02T16:49:44.783 に答える
0

スレッドを使用しているときは thread.doStuff();、スレッドを使用していません。スレッドを使用するにはthread.start()、内部的にメソッドを呼び出すメソッドを呼び出す必要がありますrun()

于 2012-12-02T16:32:31.183 に答える
0
 Thread[] threads = new Thread()[10];
    for (int i = 0 ; i<10 ; i++) {
        if ( i<5) {
          threads[i] = new Thread(new WorkerA());
        } else {
          threads[i] = new Thread(new WorkerB());
        }
        threads[i].start();
    }

最初は配列を作成していますが、正しく使用していません。オブジェクトを配列に割り当てることはできませんか? 次に、start()メソッドを呼び出してスレッドをバックグラウンドで実行し、その実行メソッドを呼び出す必要があります。

ワーカーは次のようになります。

class WorkerA implements Runnable {            

    public void run (){
        ...
        // put here your code from doStuff in one Version
        ...
    }

}

class WorkerB implements Runnable {

    public void run (){
        ...
        // put here your code from doStuff in an other Version
        ...
    }

}

をループ内で呼び出す代わりにthread[i].start()、配列への参照を使用してどこでも呼び出すことができるようになりました。

于 2012-12-02T16:37:59.603 に答える
0

そのために使えますRunnable

// Dictate what work needs to be done
Runnable work = new Work(); // or new OtherWork();

Thread thread = new Thread(work);
thread.start();

class Work implements Runnable {
    public void run(){
        System.out.println("do stuff");
    }
}

class OtherWork implements Runnable {
    public void run() {
        System.out.println(" do other stuff");
    }
}

EDIT :
タスクごとにスレッドを作成 (および破棄) する代わりに、スレッド プールを使用することをお勧めします。これは、スレッドの作成/破棄にいくらかのオーバーヘッドがあり、タスクを実行する必要がある同時実行数などの管理が容易になるためです。

とにかく、クラスを使用して自分でスレッド プールを作成することもできますThreadが、それは大変な作業であり、正しく行うのは困難です。代わりに、JDK で利用可能な既製のソリューションを使用することをお勧めします。次のように使用できます。

ExecutorService threadPool = Executors.newFixedThreadPool(4);
threadPool.execute(new Work());
threadPool.execute(new OtherWork());

// After submitting all your task (or when your application wants to terminate)
// You should call shutdown() on the thread pool so that the JVM can exit
threadPool.shutdown();
于 2012-12-02T16:40:43.053 に答える