《Java程序员面试秘笈》—— 1.3 线程信息的获取和设置

本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.3节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.3 线程信息的获取和设置

Thread类有一些保存信息的属性,这些属性可以用来标识线程,显示线程的状态或者控制线程的优先级。

ID:保存了线程的唯一标示符。

Name:保存了线程名称

Priority:保存了线程对象的优先级。线程的优先级是从1到10,其中1是最低优先级;10是最高优先级。我们并不推荐去改变线程的优先级,然而,在需要的时候,也可以这么做。

Status:保存了线程的状态。在Java中,线程的状态有6种:new、runnable、blocked、waiting、time waiting或者 terminated。

在本节,我们将编写程序为10个线程指定名称和优先级,并且输出它们的状态信息直到线程结束。每个线程都将计算一个数字的乘法表。

准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。

范例实现
按照接下来的步骤实现本节的范例。

1.创建一个名为Calculator的类,它实现了Runnable接口。
``
public class Calculator implements Runnable {``
2.声明一个名为number的私有int属性。编写这个类的一个构造器,用来为属性number设置值。

private int number;
public Calculator(int number) {
  this.number=number;
}```
3.编写run()方法。这个方法用来执行我们创建的线程的指令,本范例中它将对指定的数字进行乘法表运算。

@Override
public void run() {
for (int i=1; i<=10; i++){

System.out.printf("%s: %d * %d = %d\n",Thread. currentThread().getName(),number,i,i*number);

}
}`
4.编写范例的主类。创建一个名为Main的类,创建的时候同时生成main()方法。

public class Main {
  public static void main(String[] args) {```
5. 创建一个容量为10的线程数组,以用来存储线程;创建一个容量为10的Thread.State数组,以用来存放这10个线程运行时的状态。

Thread threads[]=new Thread[10];
Thread.State status[]=new Thread.State[10];`
6.创建一个容量为10的Calculator对象数组,为每个对象都设置不同的数字,然后使用它们作为Thread构造器的参数来创建10个线程对象。并且将其中5个线程的优先级设置为最高,另外5个线程的优先级设置为最低。

for (int i=0; i<10; i++){
  threads[i]=new Thread(new Calculator(i));
   if ((i%2)==0){
    threads[i].setPriority(Thread.MAX_PRIORITY);
   } else {
     threads[i].setPriorit87y(Thread.MIN_PRIORITY);
   }
   threads[i].setName("Thread "+i);
}```
7.创建一个PrintWriter对象,用来把线程的状态演变写入到文件中。

try (FileWriter file = new FileWriter(".\data\log.txt");PrintWriter pw = new PrintWriter(file);){`
8.把这10个线程的状态写入文件中。现在线程的状态是NEW。

  for (int i=0; i<10; i++){
pw.println("Main : Status of Thread "+i+" : " +threads[i].getState());
       status[i]=threads[i].getState();
  }```
9.开始执行10个线程。

for (int i=0; i<10; i++){
threads[i].start();
}`
10.直到10个线程都运行完成,我们就可以查看他们的状态。所有任何一个线程的状态发生了变化,我们就会将它写入到文件中。

    boolean finish=false;
    while (!finish) {
      for (int i=0; i<10; 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<10; i++){
finish=finish &&(threads[i].getState()==State.TERMINATED);
        }
      }```
11.编写writeThreadInfo()方法,用来写下线程的ID、名称、优先级、旧的状态和新的状态。

private static void writeThreadInfo(PrintWriter pw, Thread
thread, State state) {
pw.printf("Main : Id %d - %sn",thread.getId(),thread.getName());
pw.printf("Main : Priority: %dn",thread.getPriority());
pw.printf("Main : Old State: %sn",state);
pw.printf("Main : New State: %sn",thread.getState());
pw.printf("Main : n");
}`
12.运行这个范例,然后打开log.txt文件来查看10个线程的状态演变。

工作原理
下面的截屏是log.txt文件的一部分。在这个文件里,我们可以看到最高优先级的线程比最低优先级的线程结束得早。我们也可以看到每个线程的状态演变。

fe869d7b6df5c186a604f5a0ddf299b1a96976b0

这个程序的乘法表运算显示在控制台上,每个线程的状态演变记录在log.txt里。这样你可以更清楚地看到线程的演变过程。

Thread类的属性存储了线程的所有信息。JVM使用线程的priority属性来决定某一刻由哪个线程来使用CPU,并且根据线程的情景为它们设置实际状态。

如果没有为线程指定一个名字,JVM将自动给它分配一个名字,格式是Thread-XX,其中XX是一组数字。线程的ID和状态是不允许被修改的,线程类没有提供setId()和setStatus()方法来修改它们。

更多信息
通过本节,你已经学会了如何通过Thread对象访问属性信息。但是,也可以通过实现Runnable接口的对象来访问这些属性信息。如果一个线程是以Runnable对象为参数构建的,那么也可以使用Thread类的静态方法currentThread()来访问这个线程对象。

要注意的是,如果使用setPriority()方法设置的优先级不是从1到10这个范围内的值,运行时就会抛出IllegalArgumentException异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值