Java並發編程示例(七):守護線程的創立和運轉。本站提示廣大學習愛好者:(Java並發編程示例(七):守護線程的創立和運轉)文章只能為提供參考,不一定能成為您想要的結果。以下是Java並發編程示例(七):守護線程的創立和運轉正文
Java有一種特別線程,守護線程,這類線程優先級特殊低,只要在統一法式中的其他線程不履行時才會履行。
因為守護線程具有這些特征,所以,普通用為為法式中的通俗線程(也稱為用戶線程)供給辦事。它們普通會有一個無窮輪回,或用於期待要求辦事,或用於履行義務等。它們弗成以做任何主要的任務,由於我們不肯定他們甚麼時能力分派到CPU運轉時光,並且當沒有其他線程履行時,它們就會主動終止。這類線程的一個典范運用就是Java的渣滓收受接管。
在本節示例中,我們將創立兩個線程,一個是通俗線程,向隊列中寫入事宜;別的一個是守護線程,消除隊列中的事宜,刪除存在時光跨越10秒的事宜。
知其然
依照以下步調,完成示例法式。
1.創立Event類,該類僅僅用於保留法式履行所需的事宜信息。聲明兩個屬性,一個是java.util.Date類型的的date熟習,別的一個是String類型的event屬性;然後生成這兩個屬性的讀寫辦法。代碼以下:
public class Event {
private Date date;
private String event;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
}
2.創立一個名為WriterTask的類,而且完成Runnable接口。代碼以下:
public class WriterTask implements Runnable {
3.聲明一個用來存儲事宜的隊列屬性,完成類的結構函數,而且應用其參數來初始化隊列屬性。代碼以下:
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
4.完成該義務的run()辦法,辦法中含有一個遍歷100次的輪回。在每次遍歷中,創立一個新的Event對象,然後保留到隊列中,再睡眠1秒鐘。代碼以下:
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Event event = new Event();
event.setDate(new Date());
event.setEvent(String.format("The thread %s has generated an event",
Thread.currentThread().getId()));
deque.addFirst(event);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5.創立一個名為CleanerTask的類,並繼續Thread類。代碼以下:
public class CleanerTask extends Thread {
6.聲明一個用來存儲事宜的隊列屬性,完成類的結構函數,而且應用其參數來初始化隊列屬性。在結構辦法中,經由過程挪用setDaemon()辦法,將該線程設置為守護線程。代碼以下:
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
7.完成run()辦法,辦法體內有一個無窮輪回,用於獲得以後時光,然後挪用clearn()辦法。代碼以下:
@Override
public void run() {
while (true) {
Date date = new Date();
clean(date);
}
}
8.完成clean()辦法,在該辦法內,獲得最初面的一個時光,然後檢討時光時光和以後時光的時光差,假如在10秒鐘之前創立的,則刪除以後事宜,再檢討下一個事宜。假如有事宜被刪除,則顯示打印出被刪除事宜的信息,然後還將打印出隊列的最新長度,如許便可以不雅察到法式的履行停頓。代碼以下:
private void clean(Date date) {
long difference;
boolean delete;
if (deque.size() == 0) {
return;
}
delete = false;
do {
Event e = deque.getLast();
difference = date.getTime() - e.getDate().getTime();
if (difference > 10000) {
System.out.printf("Cleaner: %s\n", e.getDate());
deque.removeLast();
delete = true;
}
} while (difference > 10000);
if (delete) {
System.out.printf("Clearner: Size of the queue: %d\n", deque.size());
}
}
9.創立法式的主類,Main類,然後完成main()辦法。代碼以下:
public class Main {
public static void main(String[] args) {
10.應用Deque類創立存儲事宜的隊列。代碼以下:
Deque<Event> deque = new ArrayDeque<>();
11.創立並啟動三個WriterTask線程和一個CleanerTask線程。代碼以下:
Deque<Event> deque = new ArrayDeque<>();
WriterTask writer = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(writer);
thread.start();
}
CleanerTask cleaner = new CleanerTask(deque);
cleaner.start();
12.履行法式,檢查履行成果。
知其所以然
剖析法式的履行成果便可以看出,隊列先增長到30,然後就在27到30之間變更,曉得法式履行停止。
法式起首從三個WriterTask線程開端履行,每一個線程先隊列增長一個事宜,然後睡眠1秒鐘。在前10秒事後,在隊列中將存在三十個事宜。在這10秒時代,當三個WriterTask線程都睡眠時,CleanerTask線程也會運轉,然則不會刪除任何事宜,由於一切的事宜的生成時光還不跨越10秒。在前10秒事後的時光裡,每秒鐘三個WriterTask向隊列中添加三個事宜;異樣,CleanerTask每秒會刪除三個事宜。所以,事宜的數量在27到30之間彷徨。
當WriterTask線程都休眠時,我們便可以自在處置時光,這段時光讓守護線程得以運轉。假如將WriterTask線程的睡眠時光設置得更短一點,那末CleanerTask線程將獲得更少的CPU運轉時光。果真如斯的話,由於CleanerTask線程一向得不到足夠的運轉時光不克不及用於刪除足夠的事宜,隊列的長度將會一向增加下去。
永無盡頭
僅能在挪用start()辦法之前,經由過程挪用setDaemon()辦法將線程設置為守護線程。一旦線程開端運轉,則不克不及修正守護狀況。
還可使用isDaemon()來檢討一個線程能否為守護線程。假如是守護線程,則前往true;假如是通俗線程,則前往false。
拿來主義
本文是從 《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為 《Java7並發示例集》 )翻譯而來,僅作為進修材料應用。沒有受權,不得用於任何貿易行動。
小有所成
本節所用的一切示例代碼的完全版。
Event類的完全代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
/**
* 事宜信息類
* Date: 2013-09-19
* Time: 22:56
*/
public class Event {
private Date date;
private String event;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
}
WriterTask類的完全代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* 每秒生成一個事宜。
* Date: 2013-09-19
* Time: 22:59
*/
public class WriterTask implements Runnable {
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Event event = new Event();
event.setDate(new Date());
event.setEvent(String.format("The thread %s has generated an event",
Thread.currentThread().getId()));
deque.addFirst(event);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
CleanerTask類的完全代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
/**
* 事宜清算
* Date: 2013-09-19
* Time: 23:33
*/
public class CleanerTask extends Thread {
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
@Override
public void run() {
while (true) {
Date date = new Date();
clean(date);
}
}
/**
* 刪除事宜。
*
* @param date
*/
private void clean(Date date) {
long difference;
boolean delete;
if (deque.size() == 0) {
return;
}
delete = false;
do {
Event e = deque.getLast();
difference = date.getTime() - e.getDate().getTime();
if (difference > 10000) {
System.out.printf("Cleaner: %s\n", e.getDate());
deque.removeLast();
delete = true;
}
} while (difference > 10000);
if (delete) {
System.out.printf("Clearner: Size of the queue: %d\n", deque.size());
}
}
}
Main類的完全代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Date: 2013-09-19
* Time: 23:54
*/
public class Main {
public static void main(String[] args) {
Deque<Event> deque = new ArrayDeque<>();
WriterTask writer = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(writer);
thread.start();
}
CleanerTask cleaner = new CleanerTask(deque);
cleaner.start();
}
}