Java にはデーモン スレッドという特別なスレッドがあり、これは優先度が非常に低く、同じプログラム内の他のスレッドが実行されていない場合にのみ実行されます。
デーモン スレッドはこのような特性を備えているため、通常、プログラム内の通常のスレッド (ユーザー スレッドとも呼ばれます) にサービスを提供するために使用されます。これらは通常、無限ループを持っているか、リクエスト サービスを待機するか、タスクを実行するために使用されます。これらは、いつ CPU 時間が割り当てられるかわからないため、重要な作業を行うことができません。また、他のスレッドが実行されなくなると自動的に終了します。このタイプのスレッドの典型的なアプリケーションは Java ガベージ コレクションです。
このセクションの例では、2 つのスレッドを作成します。1 つはキューにイベントを書き込む通常のスレッドで、もう 1 つはキュー内のイベントをクリアし、10 秒を超えて存在するイベントを削除するデーモン スレッドです。
それを知っています
サンプルプログラムを実装するには、以下の手順に従います。
1. プログラムの実行に必要なイベント情報を保存するためだけに使用される Event クラスを作成します。 2 つのプロパティを宣言し、1 つは java.util.Date タイプの date プロパティ、もう 1 つは String タイプのイベント プロパティで、これら 2 つのプロパティの読み取りメソッドと書き込みメソッドを生成します。コードは次のとおりです。
次のようにコードをコピーします。
パブリック クラス イベント {
プライベート 日付 日付;
プライベート文字列イベント。
public Date getDate() {
帰国日。
}
public void setDate(日付 date) {
this.date = 日付;
}
public String getEvent() {
リターンイベント。
}
public void setEvent(String イベント) {
this.event = イベント;
}
}
2. WriterTask という名前のクラスを作成し、Runnable インターフェイスを実装します。コードは次のとおりです。
次のようにコードをコピーします。
public class WriterTask は Runnable {を実装します
3. イベントの保存に使用するキュー属性を宣言し、クラスのコンストラクターを実装し、そのパラメーターを使用してキュー属性を初期化します。コードは次のとおりです。
次のようにコードをコピーします。
プライベート Deque<Event> デキュー;
public WriterTask(Deque<Event> deque) {
this.deque = デック;
}
4. このタスクの run() メソッドを実装します。これには 100 回実行するループが含まれます。走査するたびに、新しい Event オブジェクトが作成されてキューに保存され、1 秒間スリープします。コードは次のとおりです。
次のようにコードをコピーします。
@オーバーライド
public void run() {
for (int i = 0; i < 100; i++) {
イベント イベント = new Event();
イベント.setDate(新しい日付());
event.setEvent(String.format("スレッド %s がイベントを生成しました",
Thread.currentThread().getId()));
deque.addFirst(イベント);
試す {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5. CleanerTask という名前のクラスを作成し、Thread クラスを継承します。コードは次のとおりです。
次のようにコードをコピーします。
public class CleanerTask extends Thread {
6. イベントの保存に使用するキュー属性を宣言し、クラスのコンストラクターを実装し、そのパラメーターを使用してキュー属性を初期化します。構築メソッドで、setDaemon() メソッドを呼び出して、スレッドをデーモン スレッドとして設定します。コードは次のとおりです。
次のようにコードをコピーします。
プライベート Deque<Event> デキュー;
public CleanerTask(Deque<Event> deque) {
this.deque = デック;
setDaemon(true);
}
7. run() メソッドを実装します。メソッド本体には、現在時刻を取得して、clearn() メソッドを呼び出すための無限ループがあります。コードは次のとおりです。
次のようにコードをコピーします。
@オーバーライド
public void run() {
while (true) {
日付 date = new Date();
クリーン(日付);
}
}
8. clean() メソッドを実装します。このメソッドでは、前回の時刻を取得し、10 秒前に作成された場合は現在のイベントを削除し、次の時刻を確認します。イベント。イベントが削除されると、削除されたイベントに関する情報が出力され、最新のキューの長さも出力されるため、プログラムの実行の進行状況を確認できます。コードは次のとおりです。
次のようにコードをコピーします。
private void clean(Date date) {
長い差。
ブール値の削除;
if (deque.size() == 0) {
戻る;
}
削除 = false;
する {
イベント e = deque.getLast();
差 = date.getTime() - e.getDate().getTime();
if (差 > 10000) {
System.out.printf("クリーナー: %s/n", e.getDate());
deque.removeLast();
削除 = true;
}
while (差 > 10000);
if (削除) {
System.out.printf("Clearner: キューのサイズ: %d/n", deque.size());
}
}
9. プログラムのメインクラスである Main クラスを作成し、main() メソッドを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリッククラス Main {
public static void main(String[] args) {
10. Deque クラスを使用して、イベントを保存するキューを作成します。コードは次のとおりです。
次のようにコードをコピーします。
Deque<Event> deque = new ArrayDeque<>();
11. 3 つの WriterTask スレッドと 1 つの CleanerTask スレッドを作成して開始します。コードは次のとおりです。
次のようにコードをコピーします。
Deque<Event> deque = new ArrayDeque<>();
WriterTask ライター = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
スレッド thread = 新しいスレッド (ライター);
thread.start();
}
CleanerTask クリーナー = new CleanerTask(deque);
クリーナー.スタート();
12. プログラムを実行し、実行結果を確認します。
理由を知っています
プログラムの実行結果を分析すると、キューは最初に 30 に増加し、その後プログラムの実行が終了するまで 27 と 30 の間で変化することがわかります。
プログラムはまず 3 つの WriterTask スレッドから実行を開始し、各スレッドは最初にイベントをキューに追加し、その後 1 秒間スリープします。最初の 10 秒が経過すると、キューには 30 個のイベントが存在します。この 10 秒間、3 つの WriterTask スレッドがすべてスリープ状態になると、CleanerTask スレッドも実行されますが、すべてのイベントの生成時間は 10 秒を超えないため、イベントは削除されません。最初の 10 秒後、3 つの WriterTask は 1 秒ごとに 3 つのイベントをキューに追加します。同様に、CleanerTask は 1 秒ごとに 3 つのイベントを削除します。したがって、イベントの数は 27 ~ 30 の間で推移します。
WriterTask スレッドがすべてスリープ状態になると、時間を自由に処理できるようになり、その間にデーモン スレッドを実行できるようになります。 WriterTask スレッドのスリープ時間を短く設定すると、CleanerTask スレッドの CPU 実行時間は短くなります。この場合、CleanerTask スレッドは十分なイベントを削除するのに十分な実行時間を取得できないため、キューの長さは増加し続けます。
終わりのない
スレッドをデーモン スレッドとして設定するには、start() メソッドを呼び出す前に setDaemon() メソッドを呼び出す必要があります。スレッドの実行が開始されると、デーモンの状態を変更することはできません。
isDaemon() を使用して、スレッドがデーモン スレッドかどうかを確認することもできます。デーモン スレッドの場合は true を返し、通常のスレッドの場合は false を返します。
ドクトリンを使用する
この記事は「Java 7 Concurrency Cookbook」(D Gua Ge が「Java7 Concurrency Example Collection」として盗用しました) を翻訳したものであり、学習教材としてのみ使用されます。許可なく商業目的で使用することはできません。
小さな成功
このセクションで使用されるすべてのサンプル コードの完全なバージョン。
Event クラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Dateをインポートします。
/**
※イベント情報教室
* 日付: 2013-09-19
* 時間: 22:56
*/
パブリック クラス イベント {
プライベート 日付 日付;
プライベート文字列イベント。
public Date getDate() {
帰国日。
}
public void setDate(日付 date) {
this.date = 日付;
}
public String getEvent() {
リターンイベント。
}
public void setEvent(String イベント) {
this.event = イベント;
}
}
WriterTask クラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Dateをインポートします。
インポートjava.util.Deque;
java.util.concurrent.TimeUnitをインポートします。
/**
* 毎秒イベントを生成します。
* 日付: 2013-09-19
* 時間: 22:59
*/
public class WriterTask は Runnable {を実装します
プライベート Deque<Event> デキュー;
public WriterTask(Deque<Event> deque) {
this.deque = デック;
}
@オーバーライド
public void run() {
for (int i = 0; i < 100; i++) {
イベント イベント = new Event();
イベント.setDate(新しい日付());
event.setEvent(String.format("スレッド %s がイベントを生成しました",
Thread.currentThread().getId()));
deque.addFirst(イベント);
試す {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
CleanerTask クラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Dateをインポートします。
インポートjava.util.Deque;
/**
* イベントのクリーンアップ
* 日付: 2013-09-19
* 時間: 23:33
*/
public class CleanerTask extends Thread {
プライベート Deque<Event> デキュー;
public CleanerTask(Deque<Event> deque) {
this.deque = デック;
setDaemon(true);
}
@オーバーライド
public void run() {
while (true) {
日付 date = new Date();
クリーン(日付);
}
}
/**
※イベントを削除します。
*
* @param 日付
*/
private void clean(Date date) {
長い差。
ブール値の削除;
if (deque.size() == 0) {
戻る;
}
削除 = false;
する {
イベント e = deque.getLast();
差 = date.getTime() - e.getDate().getTime();
if (差 > 10000) {
System.out.printf("クリーナー: %s/n", e.getDate());
deque.removeLast();
削除 = true;
}
while (差 > 10000);
if (削除) {
System.out.printf("Clearner: キューのサイズ: %d/n", deque.size());
}
}
}
Mainクラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe7;
インポートjava.util.ArrayDeque;
インポートjava.util.Deque;
/**
* 日付: 2013-09-19
* 時間: 23:54
*/
パブリッククラス Main {
public static void main(String[] args) {
Deque<Event> deque = new ArrayDeque<>();
WriterTask ライター = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
スレッド thread = 新しいスレッド (ライター);
thread.start();
}
CleanerTask クリーナー = new CleanerTask(deque);
クリーナー.スタート();
}
}