簡単な紹介
前記接触で多线程
私たちのプログラムにおける前は、いつでもコールを1つのステップを実行することができます单线程
。すべての手順を実行する必要がありますあなたの前に開発されたシングルスレッドプログラムのパスで順次実行され、後者は実行されます。単一スレッドも明らかで、より安定した相対的な利点は、マルチスレッド、よりスケーラブルなアプリケーションの開発は比較的容易です。しかし、それぞれが新しいタスクを開始する権限を待たなければならないため、マルチスレッドよりも低い効率で得られ、完了し、時にはアプリケーションは仮死の現象が現れます。完全に機能するマルチプロセッサの賛成でマルチスレッドを使用します。マルチスレッド・プロセスを作成することにより、各スレッドは、各プロセッサが完全に動作しているように、同時アプリケーションを可能にする、プロセッサ上で実行されています。マルチスレッドは、Javaを学習の非常に重要な側面である、Javaは各プログラマは基本的なスキルを習得しなければならないということです。この記事では、Javaマルチスレッドまとめのいくつかの基本的な知識についてです。
プロセスとスレッドの違い
プロセス
プロセスは操作系统资源分配
、それが基礎となるオペレーティング・システムである、基本ユニット生じる活性である場合、プロセッサ上のプログラムおよびデータの実行順序。実行するためのメモリへのプログラムは、それがプロセスになります。プロセスは、プログラムを実行するプロセスであり、特定の別個の機能を有します。本質的には、動的に生成されたプロセスのオペレーティングシステムでのプログラムの実行、動的な破壊の過程は、独自のライフサイクルと異なる動作状態の様々なています。一方、プロセスはまた、並行性を有し、それは(フォワード、独立によれば、他の処理と並行して一緒に予測不可能な速度を実行することができますPS:并发性和并行性是不同的概念,并行指的是同一时刻,两个及两个以上的指令在多个处理器上同时执行。而并发指的是同一时刻只有一条指令执行,但是多个进程可以被 CPU 快速交换执行,给我们感觉好像是多个执行在同时执行一样
)。
スレッド
スレッドがある任务调度和执行
とも呼ばれる基本単位、轻量级进程
スレッドIDによってスレッド、現在の命令ポインタ(PC)、セットスタックコンポーネントを登録します。スレッドがシステムリソースを所有していない、それだけで、実行時にはほとんど不可欠なリソースを持っていますが、それは同じプロセスに属するプロセスとスレッドが所有しているすべてのリソースを共有することができます。スレッドは、唯一のプロセスに属することができ、プロセスは複数のスレッドを持つことができますが、少なくとも一つのスレッドがあります。
両者の違い
- スケジュール独自のリソースの基本単位としての基本的な単位プロセスとしてスレッドのスケジューリングおよび割り当てを
- 並行処理プロセスの間に同時に実行することができるだけでなく、同じプロセスの複数のスレッド間で同時に実行することができます
- 資源の持つプロセスがリソースを持つ独立したユニットで、スレッドはシステムリソースを持っていませんが、リソースへのアクセスのプロセスの一部であります
- オーバーヘッドの作成または取り消しのプロセスを、システムが再計算されなければならないためと資源回収時に、システムのオーバーヘッドにつながる作成のコストやREVOKEスレッドよりも有意に大きいです
スレッドの道を作成します。
Javaのスレッドクラスのスレッドを表し、すべてのスレッドオブジェクトは、Javaスレッドが、次の三つの方法を中心に作成され、スレッドクラスまたはサブクラスのインスタンスでなければなりません。
Threadクラスを継承する方法
ステップ1から継承するクラス定義Thread
、クラス、および、クラスのオーバーライドrun
この方法は、タスクを完了するためにスレッドを表す、方法を
ステップ2スレッドオブジェクトを作成するために作成されThread
たクラスのサブクラスのインスタンスを
ステップ3は、 2段階のオブジェクトの呼び出しから作成されstart
たスレッドを起動する方法
/**
* @author mghio
* @date: 2019-12-07
* @version: 1.0
* @description: 通过继承 Thread 类的方式创建线程
* @since JDK 1.8
*/
public class CreateThreadByExtendsThread extends Thread {
@Override
public void run() {
IntStream.rangeClosed(1, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + " " + i));
}
public static void main(String[] args) {
CreateThreadByExtendsThread threadOne = new CreateThreadByExtendsThread();
CreateThreadByExtendsThread threadTwo = new CreateThreadByExtendsThread();
CreateThreadByExtendsThread threadThree = new CreateThreadByExtendsThread();
threadOne.start();
threadTwo.start();
threadThree.start();
}
}
复制代码
、Runnableインタフェースを達成するための第二の方法
ステップ1は、実装するクラス定義Runnable
のインタフェースを、次にインターフェイス実装run
方法を、この方法は、タスクを完了するためにスレッドを意味します
ステップ2作成するためのRunnable
クラス・インタフェースのインスタンスを、そして例としてその使用Thraed
作成するコンストラクタパラメータThread
オブジェクトクラスを、オブジェクトは実際のスレッドオブジェクトであります
ステップ3呼び出し元のスレッドオブジェクトのstart
メソッドは、スレッドを開始します
/**
* @author mghio
* @date: 2019-12-07
* @version: 1.0
* @description: 通过实现 Runnable 接口的方式创建线程
* @since JDK 1.8
*/
public class CreateThreadByImplementsRunnable implements Runnable {
@Override
public void run() {
IntStream.rangeClosed(1, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + " " + i));
}
public static void main(String[] args) {
CreateThreadByImplementsRunnable target = new CreateThreadByImplementsRunnable();
new Thread(target, "thread-one").start();
new Thread(target, "thread-two").start();
new Thread(target, "thread-three").start();
}
}
复制代码
呼び出し可能インターフェースを実現するには、3つの方法
ステップ1実装するクラス定義Callable
、インターフェイス、およびインターフェイス実装call
方法を、この方法は、タスクを完了するためのスレッドを示し、値を返します
ステップ2作成してCallable
使用して、クラスインターフェイスのインスタンスをFutureTask
ラップするクラスをCallable
対象に、FutureTask
オブジェクトがカプセル化しCallable
、オブジェクトのcall
メソッドの戻り値を
ステップ3および使用FutureTask
などのオブジェクトをThraed
の作成引数のコンストラクタThread
オブジェクト、およびオブジェクトの呼び出しstart
スレッドを起動する方法を
ステップ4コールFutureTask
オブジェクトのget
メソッドは、スレッドの実行が終了した後の戻り値を取得します
/**
* @author mghio
* @date: 2019-12-07
* @version: 1.0
* @description: 通过实现 Callable 接口的方式创建线程
* @since JDK 1.8
*/
public class CreateThreadByImplementsCallable implements Callable<Integer> {
@Override
public Integer call() {
AtomicInteger count = new AtomicInteger();
IntStream.rangeClosed(0, 10).forEach(i -> {
System.out.println(Thread.currentThread().getName() + " " + i);
count.getAndIncrement();
});
return count.get();
}
public static void main(String[] args) {
CreateThreadByImplementsCallable target = new CreateThreadByImplementsCallable();
FutureTask<Integer> futureTask = new FutureTask<>(target);
IntStream.rangeClosed(0, 10).forEach(i -> {
System.out.println(Thread.currentThread().getName() + " 的循环变量 i 的值" + i);
if (i == 8) {
new Thread(futureTask, "有返回值的线程").start();
}
});
try {
System.out.println("有返回值线程的返回值:" + futureTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
复制代码
それを見ることができる以上により、実際には、実装することにより、Runnable
インタフェースと実装をCallable
基本的に同じ方法でこれら二つのスレッドのインタフェースを作成するために、実現の使用Runnable
とCallable
するときモードインタフェースがスレッドを作成するには、スレッドクラスはインターフェイスを実装も継承することができ、他のクラス(PS:Java 单继承决定
)。このように、複数のスレッドが同じ共有できるtarget
オブジェクトを、その複数のスレッドがリソースと同じような状況に対処するための理想的です。もう一つのポイントは、それは、継承を使用しているThread
あなたは、現在のスレッドにアクセスする必要がある場合は、あなたが複数のスレッドを作成して、簡単な、などの準備をするとき、あなたが使用する必要はありませんThread.currentThread()
直接使用方法、this
現在のスレッドを得ることを。あなたが作成した場合、頻繁に実際のプロジェクトで消費閉じスレッドを作成するために、これらの3つの方法の使用は、システムリソースのパフォーマンスに影響を与え、そしてあなたがプールにスレッドプールのスレッドスレッドバックを使用できない場合は、スレッドプールからの時間がかかるので、私たちのプロジェクトの開発は主にスレッドプールを使用し、スレッドプールは、これら2つのを見てとることができたJavaスレッドプールを() 、Javaスレッド・プール(II) 。
スレッドのいくつかの状態
:スレッドが実行の動的なプロセスであり、それはまた、Javaでの農産物の死へのプロセスを、持っている、スレッドの完全なライフサイクルは、次の5つの状態の総含ん新しい状態(新)を使用する場合はnew
、キーワードおよびThread
作成したクラスまたはサブクラスをスレッドは、入力されたスレッドオブジェクトの後に、新建状态
それおよびその他のJavaだけでJVM割り当てメモリにより、オブジェクトとそのメンバーの変数値を初期化し、そして、それは、オブジェクトの呼び出しにまでこの状態のままになりますstart
方法。
レディ状態(Runnableを)スレッド・オブジェクトと呼ばれるstart
方法の後に、準備完了状態にスレッド。レディスレッドは、スケジューリングのためのJVMスケジューラを待って、レディキューに配置されます。いつでも即応の状態をスレッドはCPUスケジューリングによって実行することができます。
実行状態(実行)レディ状態の実行がCPUスケジューリングによって実行されている場合は、あなたが実行できるrun
メソッドを、スレッド状態のスレッド。最も複雑を実行中のスレッド、それがなることができ阻塞状态
、就绪状态
そして死亡状态
。スレッドになることに注意してください运行状态
だけ前の状態就绪状态
。
ブロックされた(ブロック)スレッドが実行した場合、理由は動作を停止し、CPUの使用を放棄し、一時的にいくつかの理由でブロックされた状態になるsleep
、suspend
との他の方法、リソースの解放を占領した後、スレッド运行状态
入ります阻塞状态
。再進入デバイスを得るために睡眠時間やリソースの終わりを待っています就绪状态
。障害物は、次の3つに分けることができます。
- ブロックを待っている中で
运行状态
、スレッドの呼び出しwait
方法は、スレッドが入ります等待阻塞状态
- 同期のブロッキングスレッド取得の
synchronized
ロックは同期が失敗した別のスレッドによって使用されているので、同期ロックは、スレッドが入ります同步阻塞
- 他のブロックされた呼び出し元のスレッドによって
sleep
、またはjoin
I / O要求を発行する場合、スレッドは、ブロッキング状態になります。場合はsleep
、タイムアウト、join
待機しているスレッドが終了または満了し、またはI / O処理が完了すると、スレッドバック就绪状态
。
死の状態(デッド)におけるA 运行状态
、完成スレッド実行run
方法、または他の終了条件が発生するため、スレッドが入るでしょう死亡状态
ライフサイクルのスレッド終わり。以下のように種々の状態によって表される循環より多くのスレッドは以下のとおりです。
一般的な方法をスレッド
共通の糸源に係る方法は、一つのから継承され、二つのカテゴリーに分けることができObject
、以下のように、クラスメソッド:
方法 | 説明 |
---|---|
公共の最終ネイティブ無効通知() | それが入るように、このオブジェクトのモニター上のシングルスレッド待機を覚まします就绪状态 |
公共の最終ネイティブ空のnotifyAll() | それが入るように、このオブジェクトのモニターで待機中のすべてのスレッドを覚まします就绪状态 |
公共の最終無効待機() | ・現在のスレッドがあるしましょう等待阻塞状态 、別のスレッドがオブジェクトの呼び出しまで、notify メソッドまたはnotifyAll メソッドを現在のスレッドが目覚め、それが開催されたロックを解除します |
公共の最終ネイティブ無効待機(長いタイムアウト) | ・現在のスレッドがあるしましょう等待阻塞状态 、別のスレッドがオブジェクトの呼び出しまで、notify メソッドまたはnotifyAll メソッドを、現在のスレッドが目を覚まします |
公共の最終無効待ち時間(長いタイムアウト、int型またはnanos) | ・現在のスレッドがあるしましょう等待阻塞状态 、別のスレッドがオブジェクトの呼び出しまで、notify メソッドまたはnotifyAll メソッドまたはいくつかの他のスレッドの割り込み現在のスレッド、または一定の時間を実際の現在のスレッドが目覚め超えました |
もう一つは、Thread
次のように、クラス定義の方法:
方法 | 説明 |
---|---|
公共の静的なネイティブ無効収量() | 現在実行中のスレッドオブジェクトを一時停止し、他のスレッドを実行し、yield この方法は、ロックを解放しません |
公共の静的なネイティブ無効スリープ(ロングミリ秒) | スリープ(サスペンド)にスレッドが現在指定されたミリ秒数内で実行され、sleep この方法は、ロックを解除していません |
公共の最後のボイド(参加) | プログラム実行フロー内の他のスレッドを呼び出すときjoin までの方法は、呼び出し元のスレッドがブロックされるときjoin 、実行のスレッドが完了しています |
ます。public void割り込み() | このスレッドを中断するには、このメソッドが呼び出されたときに、すぐに割り込みフラグは、スレッドに設定されています true |
パブリック静的ブールが中断() | Thread 現在のスレッドが中断されたかどうかを示すブール値を返すクラスの静的メソッドinterrupted メソッドが外部に加えて、割り込みフラグを返すが、それはまた、(割り込みフラグがセットされているために約割り込みフラグをクリアfalse ) |
パブリックブールisInterruptedを() | Thread 現在のスレッドが、中断されたかどうかを示すブール値を返すクラスインスタンスメソッドisInterrupted 方法は、単に割り込みフラグが明確末端標識されない返します |
スレッドの優先順位
各Javaスレッドは、オペレーティングシステムのスレッドスケジューリング順序を決定するのに役立ちます優先順位を持っています。Javaスレッドの優先度は、その値の範囲の整数です1(Thread.MIN_PRIORITY )~ 10(Thread.MAX_PRIORITY )
。デフォルトでは、各スレッドは、優先順位が割り当てられますNORM_PRIORITY(5)
。優先度の高いスレッドがプログラムに、より重要であり、優先度のスレッドを下げる前にプロセッサリソースを割り当てる必要があり、持っているThread
クラスが提供するsetPriority
とgetPriority
、スレッドの優先順位を変更し、取得するメソッド(という注:スレッドの優先度がスレッドを保証するものではありません実行の順序でなく、プラットフォームに非常に依存)。
参考記事