標籤:
Java裡有一種特殊的線程叫做守護(Daemon)線程,這種線程的優先順序很低,通常來說,當一個應用程式裡面沒有其他線程啟動並執行時候,守護線程才運行,當線程是程式中唯一啟動並執行線程時,守護線程執行結束後,JVM也就結束了這個程式。因此,守護線程通常被用來作為同一程式中普通線程的服務提供者,通常是無線迴圈的,以等待服務要求或者線程任務。
代碼實現
1:建立Event類,聲明兩個私人屬性
package com.packtpub.java7.concurrency.chapter1.recipe7.event;import java.util.Date;/** * Class that stores event‘s information * */public class Event { /** * Date of the event */ private Date date; /** * Message of the event */ private String event; /** * Reads the Date of the event * @return the Date of the event */ public Date getDate() { return date; } /** * Writes the Date of the event * @param date the date of the event */ public void setDate(Date date) { this.date = date; } /** * Reads the message of the event * @return the message of the event */ public String getEvent() { return event; } /** * Writes the message of the event * @param event the message of the event */ public void setEvent(String event) { this.event = event; }}View Code
2:建立WirterTask類,實現Runnable介面,聲明一個存放Event對象的隊列,並實現一個帶參數的構造器,初始化這個隊列,實現線程的run()方法,執行迴圈100次,每次迴圈中都會建立一個新的Event對象,並放入隊列中,然後休眠1秒鐘
package com.packtpub.java7.concurrency.chapter1.recipe7.task;import java.util.Date;import java.util.Deque;import java.util.concurrent.TimeUnit;import com.packtpub.java7.concurrency.chapter1.recipe7.event.Event;/** * Runnable class that generates and event every second * */public class WriterTask implements Runnable { /** * Data structure to stores the events */ Deque<Event> deque; /** * Constructor of the class * @param deque data structure that stores the event */ public WriterTask (Deque<Event> deque){ this.deque=deque; } /** * Main class of the Runnable */ @Override public void run() { // Writes 100 events for (int i=1; i<100; i++) { // Creates and initializes the Event objects Event event=new Event(); event.setDate(new Date()); event.setEvent(String.format("The thread %s has generated an event",Thread.currentThread().getId())); // Add to the data structure deque.addFirst(event); try { // Sleeps during one second TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }}View Code
3 建立CleanerTask類,並繼承Thread類,聲明存放Event對象的隊列,也實現一個帶參數的構造器,來初始化這個隊列,在這個構造器中用setDaemon()方法,把這個線程設為守護線程。實現run()方法,他將無線重複運行,並在每次運行中,取目前時間,調用clean()方法。實現clean()方法,讀取隊列的最後一個事件對象,如果這個事件是10s鐘之前建立的,將他刪除並且檢查下一個,如果有時間被刪除,clean()將列印出刪除事件的資訊,
package com.packtpub.java7.concurrency.chapter1.recipe7.task;import java.util.Date;import java.util.Deque;import com.packtpub.java7.concurrency.chapter1.recipe7.event.Event;/** * Class that review the Event data structure and delete * the events older than ten seconds * */public class CleanerTask extends Thread { /** * Data structure that stores events */ private Deque<Event> deque; /** * Constructor of the class * @param deque data structure that stores events */ public CleanerTask(Deque<Event> deque) { this.deque = deque; // Establish that this is a Daemon Thread setDaemon(true); } /** * Main method of the class */ @Override public void run() { while (true) { Date date = new Date(); clean(date); } } /** * Method that review the Events data structure and delete * the events older than ten seconds * @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.getEvent()); deque.removeLast(); delete=true; } } while (difference > 10000); if (delete){ System.out.printf("Cleaner: Size of the queue: %d\n",deque.size()); } }}View Code
4:實現主類
public class Main { /** * Main method of the example. Creates three WriterTasks and a CleanerTask * @param args */ public static void main(String[] args) { // Creates the Event data structure Deque<Event> deque=new ArrayDeque<Event>(); // Creates the three WriterTask and starts them WriterTask writer=new WriterTask(deque); for (int i=0; i<3; i++){ Thread thread=new Thread(writer); thread.start(); } // Creates a cleaner task and starts them CleanerTask cleaner=new CleanerTask(deque); cleaner.start(); }}
列印結果
Cleaner: Size of the queue: 28Cleaner: The thread 9 has generated an eventCleaner: Size of the queue: 28Cleaner: The thread 11 has generated an eventCleaner: Size of the queue: 29Cleaner: The thread 10 has generated an eventCleaner: Size of the queue: 28Cleaner: The thread 9 has generated an eventCleaner: Size of the queue: 28Cleaner: The thread 11 has generated an eventCleaner: Size of the queue: 29Cleaner: The thread 10 has generated an eventCleaner: Size of the queue: 28Cleaner: The thread 9 has generated an eventCleaner: Size of the queue: 28Cleaner: The thread 11 has generated an eventCleaner: Size of the queue: 29Cleaner: The thread 10 has generated an eventCleaner: Size of the queue: 29Cleaner: The thread 9 has generated an eventCleaner: Size of the queue: 28
我們會發現,隊列中的對象會不斷增長至30個,然後程式結束,隊列的長度維持在27-30之間,這個程式有3個WriteTask線程,每個線程向隊列寫入一個事件,然後休眠1秒鐘,在第一個10s中,隊列中有30個事件,直到3個WriterTask都結束後,CleanTask才開始執行,但是他沒有刪除任何事件,因為所有的事件都小於10秒鐘,在接下來運行中,CleanTask每秒鐘刪除3個事件,同時WriteTask會寫入3個對象,所以隊列一直在27-30之間。
Java7並發編程實戰(一) 守護線程的建立和運行