程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java並發編程示例(七):守護線程的創立和運轉

Java並發編程示例(七):守護線程的創立和運轉

編輯:關於JAVA

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();
    }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved