最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行

 更新時(shí)間:2014年12月05日 10:54:49   投稿:junjie  
這篇文章主要介紹了Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行,在本節(jié)示例中,我們將創(chuàng)建兩個(gè)線程,一個(gè)是普通線程,向隊(duì)列中寫入事件,另外一個(gè)是守護(hù)線程,清除隊(duì)列中的事件,需要的朋友可以參考下

Java有一種特殊線程,守護(hù)線程,這種線程優(yōu)先級(jí)特別低,只有在同一程序中的其他線程不執(zhí)行時(shí)才會(huì)執(zhí)行。

由于守護(hù)線程擁有這些特性,所以,一般用為為程序中的普通線程(也稱為用戶線程)提供服務(wù)。它們一般會(huì)有一個(gè)無限循環(huán),或用于等待請(qǐng)求服務(wù),或用于執(zhí)行任務(wù)等。它們不可以做任何重要的工作,因?yàn)槲覀儾淮_定他們什么時(shí)才能分配到CPU運(yùn)行時(shí)間,而且當(dāng)沒有其他線程執(zhí)行時(shí),它們就會(huì)自動(dòng)終止。這類線程的一個(gè)典型應(yīng)用就是Java的垃圾回收。

在本節(jié)示例中,我們將創(chuàng)建兩個(gè)線程,一個(gè)是普通線程,向隊(duì)列中寫入事件;另外一個(gè)是守護(hù)線程,清除隊(duì)列中的事件,刪除存在時(shí)間超過10秒的事件。

知其然

按照如下步驟,實(shí)現(xiàn)示例程序。

1.創(chuàng)建Event類,該類僅僅用于保存程序執(zhí)行所需的事件信息。聲明兩個(gè)屬性,一個(gè)是java.util.Date類型的的date熟悉,另外一個(gè)是String類型的event屬性;然后生成這兩個(gè)屬性的讀寫方法。代碼如下:

復(fù)制代碼 代碼如下:

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.創(chuàng)建一個(gè)名為WriterTask的類,并且實(shí)現(xiàn)Runnable接口。代碼如下:

復(fù)制代碼 代碼如下:

public class WriterTask implements Runnable {

3.聲明一個(gè)用來存儲(chǔ)事件的隊(duì)列屬性,實(shí)現(xiàn)類的構(gòu)造函數(shù),并且利用其參數(shù)來初始化隊(duì)列屬性。代碼如下:

復(fù)制代碼 代碼如下:

private Deque<Event> deque;

public WriterTask(Deque<Event> deque) {
    this.deque = deque;
}

4.實(shí)現(xiàn)該任務(wù)的run()方法,方法中含有一個(gè)遍歷100次的循環(huán)。在每次遍歷中,創(chuàng)建一個(gè)新的Event對(duì)象,然后保存到隊(duì)列中,再睡眠1秒鐘。代碼如下:

復(fù)制代碼 代碼如下:

@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.創(chuàng)建一個(gè)名為CleanerTask的類,并繼承Thread類。代碼如下:

復(fù)制代碼 代碼如下:

public class CleanerTask extends Thread {

6.聲明一個(gè)用來存儲(chǔ)事件的隊(duì)列屬性,實(shí)現(xiàn)類的構(gòu)造函數(shù),并且利用其參數(shù)來初始化隊(duì)列屬性。在構(gòu)造方法中,通過調(diào)用setDaemon()方法,將該線程設(shè)置為守護(hù)線程。代碼如下:

復(fù)制代碼 代碼如下:

private Deque<Event> deque;

public CleanerTask(Deque<Event> deque) {
    this.deque = deque;
    setDaemon(true);
}

7.實(shí)現(xiàn)run()方法,方法體內(nèi)有一個(gè)無限循環(huán),用于獲取當(dāng)前時(shí)間,然后調(diào)用clearn()方法。代碼如下:

復(fù)制代碼 代碼如下:

@Override
public void run() {
    while (true) {
        Date date = new Date();
        clean(date);
    }
}

8.實(shí)現(xiàn)clean()方法,在該方法內(nèi),獲取最后面的一個(gè)時(shí)間,然后檢查時(shí)間時(shí)間和當(dāng)前時(shí)間的時(shí)間差,如果在10秒鐘之前創(chuàng)建的,則刪除當(dāng)前事件,再檢查下一個(gè)事件。如果有事件被刪除,則顯示打印出被刪除事件的信息,然后還將打印出隊(duì)列的最新長度,這樣就可以觀察到程序的執(zhí)行進(jìn)展。代碼如下:

復(fù)制代碼 代碼如下:

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.創(chuàng)建程序的主類,Main類,然后實(shí)現(xiàn)main()方法。代碼如下:

復(fù)制代碼 代碼如下:

public class Main {
    public static void main(String[] args) {

10.使用Deque類創(chuàng)建存儲(chǔ)事件的隊(duì)列。代碼如下:

復(fù)制代碼 代碼如下:

Deque<Event> deque = new ArrayDeque<>();

11.創(chuàng)建并啟動(dòng)三個(gè)WriterTask線程和一個(gè)CleanerTask線程。代碼如下:

復(fù)制代碼 代碼如下:

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.執(zhí)行程序,查看執(zhí)行結(jié)果。

知其所以然

分析程序的執(zhí)行結(jié)果就可以看出,隊(duì)列先增加到30,然后就在27到30之間變化,知道程序執(zhí)行結(jié)束。

程序首先從三個(gè)WriterTask線程開始執(zhí)行,每個(gè)線程先隊(duì)列增加一個(gè)事件,然后睡眠1秒鐘。在前10秒過后,在隊(duì)列中將存在三十個(gè)事件。在這10秒期間,當(dāng)三個(gè)WriterTask線程都睡眠時(shí),CleanerTask線程也會(huì)運(yùn)行,但是不會(huì)刪除任何事件,因?yàn)樗械氖录纳蓵r(shí)間還不超過10秒。在前10秒過后的時(shí)間里,每秒鐘三個(gè)WriterTask向隊(duì)列中添加三個(gè)事件;同樣,CleanerTask每秒會(huì)刪除三個(gè)事件。所以,事件的數(shù)目在27到30之間徘徊。

當(dāng)WriterTask線程都休眠時(shí),我們就可以自由處理時(shí)間,這段時(shí)間讓守護(hù)線程得以運(yùn)行。如果將WriterTask線程的睡眠時(shí)間設(shè)置得更短一點(diǎn),那么CleanerTask線程將獲取更少的CPU運(yùn)行時(shí)間。果真如此的話,因?yàn)镃leanerTask線程一直得不到足夠的運(yùn)行時(shí)間不能用于刪除足夠的事件,隊(duì)列的長度將會(huì)一直增長下去。

永無止境

僅能在調(diào)用start()方法之前,通過調(diào)用setDaemon()方法將線程設(shè)置為守護(hù)線程。一旦線程開始運(yùn)行,則不能修改守護(hù)狀態(tài)。

還可以使用isDaemon()來檢查一個(gè)線程是否為守護(hù)線程。如果是守護(hù)線程,則返回true;如果是普通線程,則返回false。

拿來主義

本文是從 《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為 《Java7并發(fā)示例集》 )翻譯而來,僅作為學(xué)習(xí)資料使用。沒有授權(quán),不得用于任何商業(yè)行為。

小有所成

本節(jié)所用的所有示例代碼的完整版。

Event類的完整代碼

復(fù)制代碼 代碼如下:

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類的完整代碼

復(fù)制代碼 代碼如下:

package com.diguage.books.concurrencycookbook.chapter1.recipe7;

import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;

/**
 * 每秒生成一個(gè)事件。
 * 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類的完整代碼

復(fù)制代碼 代碼如下:

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類的完整代碼

復(fù)制代碼 代碼如下:

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


相關(guān)文章

  • Spring MVC 基于URL的映射規(guī)則(注解版)

    Spring MVC 基于URL的映射規(guī)則(注解版)

    這篇文章主要介紹了Spring MVC 基于URL的映射規(guī)則(注解版) ,詳細(xì)的介紹了幾種方式,有興趣的可以了解一下
    2017-05-05
  • SpringBoot深入分析講解監(jiān)聽器模式下

    SpringBoot深入分析講解監(jiān)聽器模式下

    監(jiān)聽器模式,大家應(yīng)該并不陌生,主要的組成要素包括了事件、監(jiān)聽器以及廣播器;當(dāng)事件發(fā)生時(shí),廣播器負(fù)責(zé)將事件傳遞給所有已知的監(jiān)聽器,而監(jiān)聽器會(huì)對(duì)自己感興趣的事件進(jìn)行處理
    2022-07-07
  • 解決

    解決"XML Parser Error on line 1: 前言中不允許有內(nèi)容"錯(cuò)誤

    解決用windows自帶的記事編輯xml文件后出現(xiàn) "XML Parser Error on line 1: 前言中不允許有內(nèi)容。"的錯(cuò)誤
    2018-02-02
  • 一文詳解如何在Java中自定義異常類

    一文詳解如何在Java中自定義異常類

    這篇文章主要介紹了如何在Java中自定義異常類的相關(guān)資料,在Java編程中開發(fā)者可以通過繼承Exception類或其子類創(chuàng)建自定義異常,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • 全解史上最快的JOSN解析庫alibaba Fastjson

    全解史上最快的JOSN解析庫alibaba Fastjson

    這篇文章主要介紹了史上最快的JOSN解析庫alibaba Fastjson,對(duì)FastJson感興趣的同學(xué),一定要看一下
    2021-04-04
  • SpringCloud網(wǎng)關(guān)組件zuul實(shí)例解析

    SpringCloud網(wǎng)關(guān)組件zuul實(shí)例解析

    這篇文章主要介紹了SpringCloud網(wǎng)關(guān)組件zuul實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 如何使用Java模擬退火算法優(yōu)化Hash函數(shù)

    如何使用Java模擬退火算法優(yōu)化Hash函數(shù)

    為了解決局部最優(yōu)解問題,1983年,Kirkpatrick等提出了模擬退火算法(SA)能有效的解決局部最優(yōu)解問題。模擬退火算法包含兩個(gè)部分即Metropolis算法和退火過程。Metropolis算法就是如何在局部最優(yōu)解的情況下讓其跳出來,是退火的基礎(chǔ)
    2021-06-06
  • MyBatis框架簡介及入門案例詳解

    MyBatis框架簡介及入門案例詳解

    MyBatis是一個(gè)優(yōu)秀的持久層框架,它對(duì)jdbc的操作數(shù)據(jù)庫的過程進(jìn)行封裝,使開發(fā)者只需要關(guān)注SQL本身,而不需要花費(fèi)精力去處理例如注冊(cè)驅(qū)動(dòng)、創(chuàng)建connection、創(chuàng)建statement、手動(dòng)設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼,本文將作為最終篇為大家介紹MyBatis的使用
    2022-08-08
  • springboot中獲取配置文件中屬性值的幾種方式小結(jié)

    springboot中獲取配置文件中屬性值的幾種方式小結(jié)

    本文主要介紹了springboot中獲取配置文件中屬性值的幾種方式小結(jié),主要介紹了六種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • HashMap原理的深入理解

    HashMap原理的深入理解

    這篇文章主要介紹了對(duì)HashMap原理的理解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評(píng)論

双城市| 繁昌县| 临朐县| 新沂市| 江阴市| 永兴县| 宜君县| 宁强县| 浦江县| 宁波市| 万全县| 闸北区| 牟定县| 祁阳县| 车致| 萨嘎县| 剑河县| 宣汉县| 凉山| 香河县| 靖江市| 亚东县| 陆良县| 孟村| 和龙市| 凭祥市| 万山特区| 邯郸县| 土默特右旗| 雷州市| 毕节市| 类乌齐县| 驻马店市| 施秉县| 石门县| 乐安县| 建湖县| 盈江县| 阳谷县| 彩票| 秦皇岛市|