web-dev-qa-db-ja.com

真に非同期のJavaスレッドをどのように実装しますか

2つの操作を実行する必要がある関数があります。1つは速く終了し、もう1つは実行に長い時間がかかります。実行時間の長い操作をスレッドに委任したいのですが、スレッドがいつ終了するかは気にしませんが、スレッドは完了する必要があります。以下に示すようにこれを実装しましたが、start()呼び出しの後に関数が終了するため、2番目の操作は完了しません。関数が確実に戻るが、2番目の操作スレッドもその実行を終了し、親スレッドに依存していないことを確認するにはどうすればよいですか?

public void someFunction(String data)
{
   smallOperation()
   SecondOperation a = new SecondOperation();
   Thread th = new Thread(a);
   th.Start();
}

class SecondOperation implements Runnable
{
  public void run(){
  // doSomething long running
 }
} 
18
Ritesh M Nayak
_public void someFunction(final String data) {
    shortOperation(data);
    new Thread(new Runnable() {
        public void run(){
            longOperation(data);
        }
    }).start();
}
_

someFunctionが呼び出された場合、JVMはlongOperationを実行します。

  1. それを実行しているスレッドはdaemonとしてマークされていません(上記のコードではそうではありません)
  2. longOperation()は例外をスローせず、
  3. longOperation()ではSystem.exit()への呼び出しは行われません
41
Binil Thomas

スレッドが終了するまでJVMは終了しません。あなたが投稿したこのコードはコンパイルさえしません。おそらく問題はあなたの実際のコードにあります。

1
danben

2番目の関数が完了していない場合、関数の戻りとは関係ありません。何かがSystem.exit()を呼び出した場合、または関数が例外をスローした場合、スレッドは停止します。それ以外の場合は、メインスレッドが停止した場合でも、完了するまで実行されます。新しいスレッドをデーモンに設定することでそれを防ぐことができますが、ここではそうしていません。

1
Yishai

私があなたの質問を正しければ、someFunction()を呼び出し、短いsmallOperation()を実行し、SecondOperationへのスレッドを実行し、この関数から返されたときに、 SecondOperationが完了しました。

私が提案したフローが正しい場合、次の行を追加するだけで済みます:

public void someFunction(String data)
{
   smallOperation()
   SecondOperation a = new SecondOperation();
   Thread th = new Thread(a);
   th.Start();
   th.join(); //add this line to make your MainThread await for this to finish . 
}

class SecondOperation implements Runnable
{
  public void run(){
  // doSomething long running
 }
} 

これを見てみましょう article は、「スレッドでjoin()メソッドを呼び出すと、呼び出し元のスレッドは待機状態になります。参照されたスレッドが終了するまで待機状態のままです。 」あなたが達成しようとしていること

そうでない場合、SecondOperationが終了したときに通知を受け取りたい場合は、 asyncTask を使用することをお勧めします

0
Saeed Jinat

modern Javaを使用したソリューション

public void someFunction(String data) {
    smallOperation();
    new Thread(() -> {
        // doSomething long running
    }).start();
}
0
shx

この質問に答えるのは遅いかもしれませんが、これが実際の解決策です。実行可能ファイルをExecutorServiceに追加するだけです。

import Java.util.concurrent.ExecutorService;
import Java.util.concurrent.Executors;

ExecutorService executor = Executors.newFixedThreadPool(10);
        executor.execute(new Runnable() {
            @Override
            public void run() {
                //your code
            }
        });
0
Abhishek Kumar