この記事では、java に関する関連知識を提供します。主に、Thread クラスの継承や FutureTask ラッパーを介した Callable インターフェイスの実装など、マルチスレッドを実装する 4 つの方法に関連する問題を整理します。 Thread スレッドを作成し、ExecutorService、Callable、Future を使用して返された結果でマルチスレッドを実装するなどです。見てみましょう。皆さんのお役に立てれば幸いです。
推奨学習: 「Java ビデオ チュートリアル 」
Javaマルチスレッド実装方法 主に 4 つのタイプがあります:
Thread クラスを継承し、Runnable インターフェイスを実装します。
Callable インターフェイスを実装して Thread スレッドを作成します。 FutureTask ラッパーを介して
ExecutorService と Callable
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start();2. Runnable インターフェイスを実装してスレッドを作成するクラスが別のクラスを拡張している場合、Thread を直接拡張することはできません。この時点で、Runnable インターフェイスを実装できます。
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }MyThread を開始するには、最初に Thread をインスタンス化し、独自の MyThread インスタンスを渡す必要があります:
MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start();実際には、Runnable ターゲット パラメータが に渡されるとき、 Thread、Thread の run() メソッドは target.run() を呼び出し、JDK ソース コードを参照します:
public void run() { if (target != null) { target.run(); } }3. Callable インターフェイスを実装して、FutureTask ラッパー を通じて Thread スレッドを作成します。 Callable インターフェイス (メソッドは 1 つだけです) 定義は次のとおりです:
public interface Callable<v> { V call() throws Exception; } public class SomeCallable<v> extends OtherClass implements Callable<v> { @Override public V call() throws Exception { // TODO Auto-generated method stub return null; } }</v></v></v>
Callable<v> oneCallable = new SomeCallable<v>(); //由Callable<integer>创建一个FutureTask<integer>对象: FutureTask<v> oneTask = new FutureTask<v>(oneCallable); //注释:FutureTask<integer>是一个包装器,它通过接受Callable<integer>来创建,它同时实现了Future和Runnable接口。 //由FutureTask<integer>创建一个Thread对象: Thread oneThread = new Thread(oneTask); oneThread.start(); //至此,一个线程就创建完成了。</integer></integer></integer></v></v></integer></integer></v></v>4. ExecutorService、Callable、Future を使用して、結果を返すスレッドを実装します。ExecutorService の 3 つのインターフェイス、 Callable と Future は、実際には Executor フレームワークに属します。結果を返すスレッドはJDK1.5で導入された新機能で、この機能を使用することで戻り値を取得するために手間がかからなくなりました。また、たとえ自分で実装したとしても、抜け穴がたくさんある可能性があります。 値を返すことができるタスクは、Callable インターフェイスを実装する必要があります。同様に、値を返さないタスクは Runnable インターフェイスを実装する必要があります。 Callable タスクの実行後、Future オブジェクトを取得できます。そのオブジェクトに対して get を呼び出すことで、Callable タスクから返される Object を取得できます。 注: get メソッドはブロックされています。つまり、スレッドは結果を返さず、get メソッドは永久に待機します。 スレッド プール インターフェイス ExecutorService と組み合わせると、結果が返される伝説的なマルチスレッドを実現できます。 以下に、返された結果を含む完全なマルチスレッド テストの例を示します。これは JDK1.5 で検証されており、直接使用できます。コードは次のとおりです:
import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; /** * 有返回值的线程 */ @SuppressWarnings("unchecked") public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程序开始运行----"); Date date1 = new Date(); int taskSize = 5; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List<future> list = new ArrayList<future>(); for (int i = 0; i >>" + f.get().toString()); list.add(f); } // 关闭线程池 pool.shutdown(); // 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } class MyCallable implements Callable<object> { private String taskNum; MyCallable(String taskNum) { this.taskNum = taskNum; } public Object call() throws Exception { System.out.println(">>>" + taskNum + "任务启动"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任务终止"); return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; } }</object></future></future>
· 主な違いは、Runnable インターフェイスの run メソッドには戻り値がないことです。
· 呼び出しメソッドは、Runnable インターフェイスの戻り値を持たないことです。 Callable インターフェイスには戻り値があり、ジェネリックをサポートします Runnable インターフェイスの run メソッドは実行時例外をスローすることのみが可能で、それらをキャプチャして処理することはできません;
· Callable インターフェイスの call メソッドでは、
# 2. 新しいスレッドを開始する方法と、start メソッドと run メソッドの呼び出しの違いは何ですか?
·スレッドに関連する基本的なメソッドには、wait、notify、notifyAll、sleep、join、yield などが含まれます。スレッド オブジェクトは、スレッドを開始せずに run メソッドを呼び出します。オブジェクトのみがメソッドを呼び出します。
·スレッド オブジェクトは、start を呼び出してスレッドを開き、jvm に run メソッドを呼び出して、開いたスレッドで実行させます。start メソッドを呼び出すと、スレッドを開始してスレッドを作成できます。準備完了状態に入り、メソッドの実行だけが行われます。スレッドの共通メソッドは引き続きメインスレッドで実行されます。
3. 基本的なスレッド関連のメソッド?
·Thread wait (wait) スレッドこのメソッドを呼び出す待機状態に入ると、別のスレッドからの通知を待つか割り込まれた場合にのみ戻りますが、wait() メソッドを呼び出した後、オブジェクトのロックが解放されることに注意してください。したがって、wait メソッドは通常、同期メソッドまたは同期コード ブロックで使用されます。
·Thread sleep (sleep) sleep は現在のスレッドをスリープさせます。wait メソッドとは異なり、sleep は現在占有されているロックを解放しません。sleep(long) はスレッドを開始させます。 TIMED-WATING. 状態、および wait() メソッドにより、現在のスレッドが WATING 状態に入ります。
· スレッド イールド (収量) イールドにより、現在のスレッドは CPU 実行タイム スライスを放棄し、CPU タイム スライスをめぐって他のスレッドと再び競合します。一般に、優先度の高いスレッドは CPU タイム スライスの競合に成功する可能性が高くなりますが、これは絶対的なものではなく、一部のオペレーティング システムはスレッドの優先度に敏感ではありません。
· スレッド割り込み (割り込み) スレッドの割り込みは、スレッドに通知信号を与えることを目的としており、これはスレッド内の割り込みフラグに影響します。このため、このスレッド自体は状態 (ブロック、終了など) を変更しません
· Join は他のスレッドが join() メソッドを終了するのを待ち、他のスレッドが終了するのを待ちます。スレッドの join() メソッドは、現在のスレッドをブロック状態にし、別のスレッドに戻って終了します。その後、現在のスレッドはブロック状態から準備完了状態に変わります。 , CPU の好意を待っています。
· スレッドウェイクアップ (通知) Object クラスの Notice() メソッドは、このオブジェクト モニターで待機している単一のスレッドをウェイクアップします。すべてのスレッドがこのオブジェクトを待機している場合、スレッドの 1 つがウェイクアップするように選択されます。選択は任意です。実装の決定が行われたときに発生し、スレッドは wait() メソッドの 1 つを呼び出してオブジェクトのモニターで待機します。目覚めたスレッドは、現在のスレッドがこのオブジェクトのロックを放棄するまで実行を続行できません。 のスレッドは、オブジェクト上でアクティブに同期している他のすべてのスレッドと通常の方法で競合します。同様のメソッドとして、notifyAll() があります。これは、モニターで待機しているすべてのスレッドを再度起動します。
· ① 異なるクラスから wait(): Object クラスから; sleep(): Thread クラスから;
· ②ロックの解放について wait(): 待機処理中にロックを解放する; sleep(): 待機中にロックを解放しない
· ③ の範囲use: wait(): 同期されたコード ブロックで使用する必要があります; sleep(): どこでも使用できます;
· ④ 例外をキャッチするかどうか wait(): キャッチする必要はありません例外; sleep (): 例外をキャッチする必要がある;
マルチスレッドの原則:マルチスレッドは同時実行によって行われます。 CPU の場合、ある時点で 1 つのプログラム、つまり同時に 1 つのプロセスしか実行できず、CPU はこれらのプロセスを継続的に切り替え、各スレッドは 1 回ずつ実行されます。 CPU の実行速度が人間の感覚に比べて速すぎるため、CPU は複数のプロセスをローテーションして実行しますが、あたかも複数のプロセスが同時に実行されているように感じられます。
CPU は複数のプロセスを切り替えますが、プログラムを開きすぎると、CPU が各プロセスに切り替えるまでの時間も長くなり、マシンの動作が遅くなったように感じられます。したがって、マルチスレッドを合理的に使用すると効率が向上しますが、広範囲に使用しても効率は向上しません。
マルチスレッド技術は、主にプロセッサ ユニットでのマルチスレッド実行の問題を解決し、プロセッサ ユニットのアイドル時間を大幅に短縮し、プロセッサ ユニットのスループット能力を向上させることができます。
推奨学習: 「Java ビデオ チュートリアル 」
以上がJava でマルチスレッドを実装する 4 つの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。