序文。ペティアおじさん
そこで、ボトルに水を入れたいとします。ペティアおじさんの水のボトルと蛇口が用意されています。ペティアおじさんは今日新しい蛇口を設置していましたが、その美しさを褒め続けていました。それまでは、古くて詰まった蛇口しか使っていなかったので、瓶詰めの際には膨大なラインができていました。少し手探りしていたら、こぼれた方向から水が注がれる音が聞こえ、2分経ってもボトルはまだ注水段階にあり、後ろにはいつもの行列ができていて、頭の中にはおじさんの思いやりの姿が浮かんでいるPetya は最高の H2O 分子のみを選択してボトルに入れます。人生で訓練されたペティアおじさんは、特に攻撃的な人たちを落ち着かせ、できるだけ早く終わらせることを約束します。ボトルを飲み終えた後、彼は次のボトルを手に取り、通常の圧力をかけますが、これでは新しい蛇口のすべての機能が明らかになりません。人々は幸せではありません...
理論
マルチスレッドとは、単一プロセス内に複数のスレッドを作成するプラットフォームの機能です。スレッドの作成と実行はプロセスの作成よりもはるかに簡単であるため、1 つのプログラムで複数の並列アクションを実装する必要がある場合は、追加のスレッドが使用されます。JVM では、すべてのプログラムはメインスレッドで実行され、残りのプログラムはメインスレッドから起動されます。同じプロセス内で、スレッドは相互にデータを交換できます。新しいスレッドを開始するときは、次のメソッドを使用してそれをユーザー スレッドとして宣言できます。
setDaemon(true);
このようなスレッドは、実行中のスレッドが他に残っていない場合、自動的に終了します。スレッドには作業優先度があります (優先度の選択は、最も優先度の高いスレッドがより低い優先度のスレッドよりも早く終了することを保証するものではありません)。
- MIN_PRIORITY
- NORM_PRIORITY (デフォルト)
- MAX_PRIORITY
ストリームを操作するときの基本的な方法:
run()
– スレッドを実行します
start()
– スレッドを開始します
getName()
– スレッド名を返します
setName()
– ストリームの名前を指定します
wait()
notify()
– 継承されたメソッドの場合、スレッドはそのメソッドが別のスレッドから呼び出されるのを待ちます
notify()
– 継承されたメソッド。以前に停止したスレッドを再開します。
notifyAll()
– 継承されたメソッド、以前に停止したスレッドを再開します
sleep()
– 指定した時間ストリームを一時停止します
join()
– スレッドが完了するのを待ちます
interrupt()
– スレッドの実行を中断します
プログラムに次のような特徴がある
場合は、 新しいスレッドについて考えてみましょう。
- ネットワークアクセス
- ファイルシステムへのアクセス
- GUI
スレッドクラス
Java のスレッドは、クラス
Thread
とその子孫として表されます。以下の例は、ストリーム クラスの単純な実装です。
import static java.lang.System.out;
public class ExampleThread extends Thread{
public static void main(String[] args) {
out.println("Основной поток");
new ExampleThread().start();
}
@Override
public void run() {
out.println("Новый поток");
}
}
その結果、得られるのは
Основной поток
Новый поток
ここでは、クラスを作成し、それを class の子孫にします
Thread
。その後、 main() メソッドを記述してメインスレッドを起動し、
run()
classメソッドをオーバーライドします
Thread
。クラスのインスタンスを作成し、その継承されたメソッドを実行したら、
start()
メソッドの本体に記述されているすべての処理が実行される新しいスレッドを起動します
run()
。複雑に聞こえますが、コード例を見ればすべてが明らかになるはずです。
実行可能なインターフェース
オラクルは、新しいスレッドを開始するための インターフェース の実装も提案しています
Runnable
。これにより、前の例で唯一利用可能な継承よりも設計の柔軟性が高まります (クラスのソースを見ると、インターフェースも実装していることがわかります
Thread
)
Runnable
。新しいスレッドを作成する場合は、推奨される方法を使用してみましょう。
import static java.lang.System.out;
public class ExampleRunnable implements Runnable {
public static void main(String[] args) {
out.println("Основной поток");
new Thread(new ExampleRunnable()).start();
}
@Override
public void run() {
out.println("Новый поток");
}
}
その結果、得られるのは
Основной поток
Новый поток
例は非常によく似ています。コードを記述するときは、
run()
インターフェイス に記述された抽象メソッドを実装する必要がありました
Runnable
。新しいスレッドを立ち上げるのは少し異なります。
Thread
インターフェイス実装のインスタンスへの参照をパラメータとして渡すことにより、クラスのインスタンスを作成しました
Runnable
。このアプローチにより、クラスを直接継承せずに新しいスレッドを作成できるようになります
Thread
。
長時間の操作
次の例は、複数のスレッドを使用する利点を明確に示しています。いくつかの長い計算を必要とする単純なタスクがあるとします。この記事を書く前は、それを 1 つのメソッドで解決し、おそらく認識しやすいように
main()
別のメソッド (場合によってはクラス) に分割していましたが、本質は同じです。すべての操作は順番に実行されます。重量のある計算をシミュレートし、その実行時間を測定してみましょう。
public class ComputeClass {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 1");
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 2");
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 3");
long timeSpent = System.currentTimeMillis() - startTime;
System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
}
}
その結果、得られるのは
complete 1
complete 2
complete 3
программа выполнялась 9885 миллисекунд
実行時間にはまだ改善の余地が多く、その間ずっと空白の出力画面が表示されます。状況はペティアおじさんの話と非常によく似ていますが、その役割を私たち開発者が利用していないだけです。最新のデバイスのすべての機能。改善してまいります。
public class ComputeClass {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
new MyThread(1).start();
new MyThread(2).start();
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 3");
long timeSpent = System.currentTimeMillis() - startTime;
System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
}
}
class MyThread extends Thread{
int n;
MyThread(int n){
this.n = n;
}
@Override
public void run() {
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete " + n);
}
}
その結果、得られるのは
complete 1
complete 2
complete 3
программа выполнялась 3466 миллисекунд
実行時間が大幅に短縮されました (マルチスレッドをサポートしていないプロセッサでは、この効果が得られないか、実行時間が増加する可能性があります)。スレッドが順序どおりに終了しない可能性があること、および開発者がアクションの予測可能性が必要な場合は、特定のケースに対して独立して実装する必要があることに注意してください。
スレッドグループ
Java のスレッドはグループに結合できます。このためにクラスが使用されます
ThreadGroup
。グループには、単一のスレッドとグループ全体の両方を含めることができます。これは、接続が失われた場合など、ネットワークに関連するフローを中断する必要がある場合に便利です。
グループの詳細については、こちらをご覧ください。 これでトピックがより明確になり、ユーザーが満足できることを願っています。
GO TO FULL VERSION