欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)編程示例(二):獲取和設(shè)置線程信息

 更新時(shí)間:2014年12月05日 09:43:52   投稿:junjie  
這篇文章主要介紹了Java并發(fā)編程示例(二):獲取和設(shè)置線程信息,本文是系列文章的第二篇,本文著重講解Thread類的幾個(gè)重要屬性,需要的朋友可以參考下

Thread類包含幾個(gè)屬性,這些屬性所表示的信息能幫助我們識(shí)別線程、觀察其狀態(tài)、控制其優(yōu)先級(jí)等。這些線程包括如下幾種:

ID: 該屬性表示每個(gè)線程的唯一標(biāo)識(shí);
Name: 該屬性存儲(chǔ)每個(gè)線程的名稱;
Priority: 該屬性存儲(chǔ)每個(gè)Thread對(duì)象的優(yōu)先級(jí)。線程優(yōu)先級(jí)分1到10十個(gè)級(jí)別,1表示最低優(yōu)先級(jí),10表示最高優(yōu)先級(jí)。并不推薦修改線程的優(yōu)先級(jí),但是如果確實(shí)有這方面的需求,也可以嘗試一下。
Status: 該屬性存儲(chǔ)線程的狀態(tài)。線程共有六種不同的狀態(tài):新建(new)、運(yùn)行(runnable)、阻塞(blocked)、等待(waiting)、限時(shí)等待(time waiting)或者終止(terminated)。線程的狀態(tài)必定是其中一種。

在本小節(jié),我們將開發(fā)一個(gè)程序,程序中新建十個(gè)線程,并且設(shè)定每個(gè)線程的名稱和優(yōu)先級(jí)。然后執(zhí)行線程,觀察線程的狀態(tài)信息,直到線程執(zhí)行結(jié)束。再說明一點(diǎn),這些線程還是計(jì)算一個(gè)數(shù)的乘法表。

知其然

按照下面所示步驟,來實(shí)現(xiàn)該示例:

1.創(chuàng)建一個(gè)名為 Calculator的類,實(shí)現(xiàn)Runnable接口。代碼如下:

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

public class Calculator implements Runnable {

2.聲明一個(gè)私有的整形屬性,名稱為number,實(shí)現(xiàn)該類的構(gòu)造函數(shù)來初始化剛剛聲明的屬性。代碼如下:

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

private int number;

public Calculator(int number) {
    this.number = number;
}

3.實(shí)現(xiàn)run()方法,該方法是我們創(chuàng)建的線程執(zhí)行時(shí)運(yùn)行的程序(instruction),故而該方法用于計(jì)算乘法表。具體代碼如下:

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

@Override
public void run() {
    for (int i = 0; i < 10; i++) {
        System.out.printf("%s: %d * %d = %d\n",
                Thread.currentThread().getName(),
                number, i, i * number);
    }
}

4.現(xiàn)在,我們來實(shí)現(xiàn)示例應(yīng)用的主類(main class)。創(chuàng)建名為Main的類,在該類中添加main方法。代碼如下:
復(fù)制代碼 代碼如下:

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

5.創(chuàng)建兩個(gè)包含十個(gè)元素?cái)?shù)組,一個(gè)是Thread類型的,一個(gè)是Thread.State類型,然后全部初始化。這兩個(gè)數(shù)組,一個(gè)用于存儲(chǔ)我們將以執(zhí)行的線程,另外一個(gè)存儲(chǔ)這些線程的狀態(tài)。代碼如下:

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

Thread[] threads = new Thread[10];
Thread.State[] status = new Thread.State[threads.length];

6.創(chuàng)建十個(gè)Calculator對(duì)象,并且使用不同的數(shù)來初始化每個(gè)對(duì)象。使用這些Calculator對(duì)象創(chuàng)建十個(gè)Thread對(duì)象,存儲(chǔ)到上面的創(chuàng)建數(shù)組中。同時(shí),設(shè)置這些線程的優(yōu)先級(jí),五個(gè)設(shè)置成最高優(yōu)先級(jí);五個(gè)設(shè)置成最低優(yōu)先級(jí)。代碼如下:

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

for (int i = 0; i < threads.length; i++) {
    threads[i] = new Thread(new Calculator(i));
    if ((i % 2) == 0) {
        threads[i].setPriority(Thread.MAX_PRIORITY);
    } else {
        threads[i].setPriority(Thread.MIN_PRIORITY);
    }
    threads[i].setName("Thread-" + i);
}

7.創(chuàng)建一個(gè)PrintWriter對(duì)象,用于將線程狀態(tài)的變換記錄到文件中。代碼如下:
復(fù)制代碼 代碼如下:

try (FileWriter file = new FileWriter("D:\\thread.log");
     PrintWriter pw = new PrintWriter(file)) {

這里使用了Java7的語法,所以請(qǐng)將JDK升級(jí)到第七版,把編譯工具設(shè)置成Java7。否則會(huì)報(bào)語法錯(cuò)誤。

8.將所有線程的狀態(tài)寫到文件中?,F(xiàn)在,現(xiàn)在的狀態(tài)應(yīng)該是新建(NEW)。代碼如下:

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

for (int i = 0; i < threads.length; i++) {
    Thread thread = threads[i];
    pw.println("Main: Status of Thread " + i +
            " : " + threads[i].getState());
    status[i] = threads[i].getState();
}

9.啟動(dòng)所有線程。代碼入下:
復(fù)制代碼 代碼如下:

for (int i = 0; i < threads.length; i++) {
    threads[i].start();
}

10.另外一方面,我們一直監(jiān)控線程,直到線程執(zhí)行結(jié)束。如果我們檢測(cè)到線程的狀態(tài)有所改變,則立即將線程狀態(tài)寫入到文件中。代碼如下:
復(fù)制代碼 代碼如下:

boolean finish = false;

while (!finish) {
    for (int i = 0; i < threads.length; i++) {
        if (threads[i].getState() != status[i]) {
            writeThreadInfo(pw, threads[i], status[i]);
            status[i] = threads[i].getState();
        }
    }
    finish = true;
    for (int i = 0; i < threads.length; i++) {
        finish = finish
                && (threads[i].getState() == Thread.State.TERMINATED);
    }
}

11.實(shí)現(xiàn)writeThreadInfo方法,該方法將線程的ID、名稱、優(yōu)先級(jí)、舊的狀態(tài)、新的狀態(tài)寫入到文件中。代碼如下:

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

/**
 * 將一個(gè)線程的狀態(tài)輸出到一個(gè)文件中。
 *
 * @param pw     PrintWriter對(duì)象
 * @param thread 需要輸出狀態(tài)的線程對(duì)象
 * @param state  線程的舊狀態(tài)
 */
private static void writeThreadInfo(PrintWriter pw,
                                  Thread thread, Thread.State state) {
    pw.printf("Main : Id %d = %s\n", thread.getId(), thread.getName());
    pw.printf("Main : Priority: %d\n", thread.getPriority());
    pw.printf("Main : Old State: %s\n", state);
    pw.printf("Main : New State: %s\n", thread.getState());
    pw.printf("Main : ********************************\n");
}

12.運(yùn)行該示例,然后打開thread.log文件,查看所有線程的演化過程。

知其所以然

下面是thread.log文件的內(nèi)容片段。從文件內(nèi)容可以看出,高優(yōu)先級(jí)的線程大致比低優(yōu)先級(jí)的線程較早完成執(zhí)行。另外,也可以看到每個(gè)線程的狀態(tài)演化過程。

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

Main : ********************************
Main : Id 11 = Thread-2
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: TERMINATED
Main : ********************************
Main : Id 13 = Thread-4
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: TERMINATED
Main : ********************************
Main : Id 14 = Thread-5
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: TERMINATED
Main : ********************************

下面是控制臺(tái)的輸出片段。輸出的是每個(gè)線程計(jì)算的乘法表,以及所有的線程計(jì)算過程。同時(shí),從這里可以更細(xì)粒度地看到每個(gè)線程的演化過程。

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

Thread-8: 8 * 2 = 16
Thread-8: 8 * 3 = 24
Thread-8: 8 * 4 = 32
Thread-6: 6 * 0 = 0
Thread-6: 6 * 1 = 6
Thread-6: 6 * 2 = 12
Thread-6: 6 * 3 = 18
Thread-6: 6 * 4 = 24
Thread-6: 6 * 5 = 30
Thread-6: 6 * 6 = 36
Thread-6: 6 * 7 = 42
Thread-6: 6 * 8 = 48
Thread-6: 6 * 9 = 54
Thread-5: 5 * 0 = 0
Thread-5: 5 * 1 = 5
Thread-5: 5 * 2 = 10
Thread-5: 5 * 3 = 15
Thread-5: 5 * 4 = 20

Thread類有可以存儲(chǔ)線程信息所需的所有屬性。Java虛擬機(jī)使用線程優(yōu)先級(jí)來每個(gè)時(shí)刻調(diào)度一個(gè)線程來使用CPU,并且根據(jù)線程的情況來設(shè)置其每個(gè)線程的狀態(tài)。

如果沒有設(shè)置線程的名稱,Java虛擬機(jī)會(huì)使用這種格式來時(shí)分配一個(gè)名稱,Thread-XX,其中XX是一個(gè)數(shù)字。我們不能修改線程的ID以及線程的狀態(tài)。Thread類也沒有實(shí)現(xiàn)setId()和setStatus()方法,以允許做出這些修改。

永無止境

在本節(jié),我們學(xué)習(xí)了如何使用Thread對(duì)象來訪問線程信息。其實(shí),Runnable的實(shí)現(xiàn)類也運(yùn)行我們?cè)L問這些信息。Thread類的靜態(tài)方法currentThread()可以獲取正在執(zhí)行的Runnable實(shí)現(xiàn)類的對(duì)象,進(jìn)而訪問線程的信息。

需要注意的是,如果嘗試設(shè)置1到10以外的優(yōu)先級(jí),setPriority()會(huì)拋出名為IllegalArgumentException的異常,

拿來主義

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

小有所成

Calculator類的完整代碼

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

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

/**
 * Date: 2013-09-13
 * Time: 19:49
 */
public class Calculator implements Runnable {
    private int number;

    public Calculator(int number) {
        this.number = number;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.printf("%s: %d * %d = %d\n",
                    Thread.currentThread().getName(),
                    number, i, i * number);
        }
    }
}

Main類的完整代碼

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

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

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Date: 2013-09-13
 * Time: 19:51
 */
public class Main {
    public static void main(String[] args) {
        Thread[] threads = new Thread[10];
        Thread.State[] status = new Thread.State[threads.length];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Calculator(i));
            if ((i % 2) == 0) {
                threads[i].setPriority(Thread.MAX_PRIORITY);
            } else {
                threads[i].setPriority(Thread.MIN_PRIORITY);
            }
            threads[i].setName("Thread-" + i);
        }

        try (FileWriter file = new FileWriter("D:\\thread.log");
             PrintWriter pw = new PrintWriter(file)) {
            for (int i = 0; i < threads.length; i++) {
                Thread thread = threads[i];
                pw.println("Main: Status of Thread " + i +
                        " : " + threads[i].getState());
                status[i] = threads[i].getState();
            }

            for (int i = 0; i < threads.length; i++) {
                threads[i].start();
            }

            boolean finish = false;

            while (!finish) {
                for (int i = 0; i < threads.length; i++) {
                    if (threads[i].getState() != status[i]) {
                        writeThreadInfo(pw, threads[i], status[i]);
                        status[i] = threads[i].getState();
                    }
                }
                finish = true;
                for (int i = 0; i < threads.length; i++) {
                    finish = finish
                            && (threads[i].getState() == Thread.State.TERMINATED);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 將一個(gè)線程的狀態(tài)輸出到一個(gè)文件中。
     *
     * @param pw     PrintWriter對(duì)象
     * @param thread 需要輸出狀態(tài)的線程對(duì)象
     * @param state  線程的舊狀態(tài)
     */
    private static void writeThreadInfo(PrintWriter pw,
                                      Thread thread, Thread.State state) {
        pw.printf("Main : Id %d = %s\n",
                    thread.getId(), thread.getName());
        pw.printf("Main : Priority: %d\n", thread.getPriority());
        pw.printf("Main : Old State: %s\n", state);
        pw.printf("Main : New State: %s\n", thread.getState());
        pw.printf("Main : ********************************\n");
    }
}

相關(guān)文章

  • 分析并發(fā)編程之LongAdder原理

    分析并發(fā)編程之LongAdder原理

    LongAdder類是JDK1.8新增的一個(gè)原子性操作類。AtomicLong通過CAS算法提供了非阻塞的原子性操作,相比受用阻塞算法的同步器來說性能已經(jīng)很好了,但是JDK開發(fā)組并不滿足于此,因?yàn)榉浅8悴l(fā)的請(qǐng)求下AtomicLong的性能是不能讓人接受的
    2021-06-06
  • java調(diào)用百度的接口獲取起-止位置的距離

    java調(diào)用百度的接口獲取起-止位置的距離

    本文主要介紹了java調(diào)用百度的接口獲取起-止位置的距離,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • spring-boot通過@Scheduled配置定時(shí)任務(wù)及定時(shí)任務(wù)@Scheduled注解的方法

    spring-boot通過@Scheduled配置定時(shí)任務(wù)及定時(shí)任務(wù)@Scheduled注解的方法

    這篇文章主要介紹了spring-boot通過@Scheduled配置定時(shí)任務(wù),文中還給大家介紹了springboot 定時(shí)任務(wù)@Scheduled注解的方法,需要的朋友可以參考下
    2017-11-11
  • 劍指Offer之Java算法習(xí)題精講字符串操作與數(shù)組及二叉搜索樹

    劍指Offer之Java算法習(xí)題精講字符串操作與數(shù)組及二叉搜索樹

    跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • Java面向?qū)ο蠡A(chǔ)詳解

    Java面向?qū)ο蠡A(chǔ)詳解

    這篇文章主要介紹了JJava面向?qū)ο蟮幕A(chǔ),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-10-10
  • 詳細(xì)介紹Spring的配置文件

    詳細(xì)介紹Spring的配置文件

    這篇文章主要為大家詳細(xì)介紹了Spring中的配置文件的命名以及它的配置文件都有些什么。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟上小編一起學(xué)習(xí)一下
    2022-10-10
  • 使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證

    使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證

    這篇文章主要為大家詳細(xì)介紹了使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • 解析Java中的默認(rèn)方法

    解析Java中的默認(rèn)方法

    這篇文章主要介紹了Java中的默認(rèn)方法,包括繼承和調(diào)用等Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • ssm框架Springmvc文件上傳實(shí)現(xiàn)代碼詳解

    ssm框架Springmvc文件上傳實(shí)現(xiàn)代碼詳解

    這篇文章主要介紹了ssm框架Springmvc文件上傳實(shí)現(xiàn)代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • springboot中通過lua腳本來獲取序列號(hào)的方法

    springboot中通過lua腳本來獲取序列號(hào)的方法

    這篇文章主要介紹了springboot中通過lua腳本來獲取序列號(hào)的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06

最新評(píng)論