Java并发编程示例(二):获取和设置线程信息
2017-08-16 21:55
686 查看
开门见山
Thread类包含几个属性,这些属性所表示的信息能帮助我们识别线程、观察其状态、控制其优先级等。这些线程包括如下几种:ID: 该属性表示每个线程的唯一标识;
Name: 该属性存储每个线程的名称;
Priority: 该属性存储每个Thread对象的优先级。线程优先级分1到10十个级别,1表示最低优先级,10表示最高优先级。并不推荐修改线程的优先级,但是如果确实有这方面的需求,也可以尝试一下。
Status: 该属性存储线程的状态。线程共有六种不同的状态:新建(new)、运行(runnable)、阻塞(blocked)、等待(waiting)、限时等待(time waiting)或者终止(terminated)。线程的状态必定是其中一种。
在本小节,我们将开发一个程序,程序中新建十个线程,并且设定每个线程的名称和优先级。然后执行线程,观察线程的状态信息,直到线程执行结束。再说明一点,这些线程还是计算一个数的乘法表。
知其然
按照下面所示步骤,来实现该示例:
1.创建一个名为 Calculator的类,实现Runnable接口。代码如下:
public class Calculator implements Runnable {
2.声明一个私有的整形属性,名称为number,实现该类的构造函数来初始化刚刚声明的属性。代码如下:
private int number;
public Calculator(int number) {
this.number = number;
}
3.实现run()方法,该方法是我们创建的线程执行时运行的程序(instruction),故而该方法用于计算乘法表。具体代码如下:
@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.现在,我们来实现示例应用的主类(main class)。创建名为Main的类,在该类中添加main方法。代码如下:
public class Main {
public static void main(String[] args) {}
5.创建两个包含十个元素数组,一个是Thread类型的,一个是Thread.State类型,然后全部初始化。这两个数组,一个用于存储我们将以执行的线程,另外一个存储这些线程的状态。代码如下:
Thread[] threads = new Thread[10];
Thread.State[] status = new Thread.State[threads.length];
6.创建十个Calculator对象,并且使用不同的数来初始化每个对象。使用这些Calculator对象创建十个Thread对象,存储到上面的创建数组中。同时,设置这些线程的优先级,五个设置成最高优先级;五个设置成最低优先级。代码如下:
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.创建一个PrintWriter对象,用于将线程状态的变换记录到文件中。代码如下:
try (FileWriter file = new FileWriter(“D:\thread.log”);
PrintWriter pw = new PrintWriter(file)) {}
这里使用了Java7的语法,所以请将JDK升级到第七版,把编译工具设置成Java7。否则会报语法错误。
8.将所有线程的状态写到文件中。现在,现在的状态应该是新建(NEW)。代码如下:
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.启动所有线程。代码入下:
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
10.另外一方面,我们一直监控线程,直到线程执行结束。如果我们检测到线程的状态有所改变,则立即将线程状态写入到文件中。代码如下:
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.实现writeThreadInfo方法,该方法将线程的ID、名称、优先级、旧的状态、新的状态写入到文件中。代码如下:
/**
将一个线程的状态输出到一个文件中。
*
@param pw PrintWriter对象
@param thread 需要输出状态的线程对象
@param state 线程的旧状态
*/
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.运行该示例,然后打开thread.log文件,查看所有线程的演化过程。
知其所以然
下面是thread.log文件的内容片段。从文件内容可以看出,高优先级的线程大致比低优先级的线程较早完成执行。另外,也可以看到每个线程的状态演化过程。Main: Status of Thread 0 : NEW
Main: Status of Thread 1 : NEW
Main: Status of Thread 2 : NEW
Main: Status of Thread 3 : NEW
Main: Status of Thread 4 : NEW
Main: Status of Thread 5 : NEW
Main: Status of Thread 6 : NEW
Main: Status of Thread 7 : NEW
Main: Status of Thread 8 : NEW
Main: Status of Thread 9 : NEW
Main : Id 10 = Thread-0
Main : Priority: 10
Main : Old State: NEW
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 11 = Thread-1
Main : Priority: 1
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 12 = Thread-2
Main : Priority: 10
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 13 = Thread-3
Main : Priority: 1
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 14 = Thread-4
Main : Priority: 10
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 15 = Thread-5
Main : Priority: 1
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 16 = Thread-6
Main : Priority: 10
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 17 = Thread-7
Main : Priority: 1
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 18 = Thread-8
Main : Priority: 10
Main : Old State: NEW
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: NEW
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 10 = Thread-0
Main : Priority: 10
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 17 = Thread-7
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 17 = Thread-7
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 15 = Thread-5
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 15 = Thread-5
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : **********************[/b]
Main : Id 13 = Thread-3
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 13 = Thread-3
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 18 = Thread-8
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 16 = Thread-6
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 14 = Thread-4
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 12 = Thread-2
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 16 = Thread-6
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 18 = Thread-8
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 18 = Thread-8
Main : Priority: 10
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 11 = Thread-1
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 11 = Thread-1
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 16 = Thread-6
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 16 = Thread-6
Main : Priority: 10
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 14 = Thread-4
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: BLOCKED
Main : [b]**********************[/b]
Main : Id 14 = Thread-4
Main : Priority: 10
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 12 = Thread-2
Main : Priority: 10
Main : Old State: BLOCKED
Main : New State: RUNNABLE
Main : [b]**********************[/b]
Main : Id 12 = Thread-2
Main : Priority: 10
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
Main : Id 19 = Thread-9
Main : Priority: 1
Main : Old State: RUNNABLE
Main : New State: TERMINATED
Main : [b]**********************[/b]
下面是控制台的输出片段。输出的是每个线程计算的乘法表,以及所有的线程计算过程。同时,从这里可以更细粒度地看到每个线程的演化过程。
Thread-0: 0 * 0 = 0
Thread-0: 0 * 1 = 0
Thread-0: 0 * 2 = 0
Thread-0: 0 * 3 = 0
Thread-0: 0 * 4 = 0
Thread-0: 0 * 5 = 0
Thread-0: 0 * 6 = 0
Thread-0: 0 * 7 = 0
Thread-0: 0 * 8 = 0
Thread-0: 0 * 9 = 0
Thread-9: 9 * 0 = 0
Thread-9: 9 * 1 = 9
Thread-9: 9 * 2 = 18
Thread-9: 9 * 3 = 27
Thread-9: 9 * 4 = 36
Thread-9: 9 * 5 = 45
Thread-9: 9 * 6 = 54
Thread-7: 7 * 0 = 0
Thread-7: 7 * 1 = 7
Thread-7: 7 * 2 = 14
Thread-7: 7 * 3 = 21
Thread-7: 7 * 4 = 28
Thread-7: 7 * 5 = 35
Thread-7: 7 * 6 = 42
Thread-7: 7 * 7 = 49
Thread-7: 7 * 8 = 56
Thread-7: 7 * 9 = 63
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-5: 5 * 5 = 25
Thread-5: 5 * 6 = 30
Thread-5: 5 * 7 = 35
Thread-5: 5 * 8 = 40
Thread-5: 5 * 9 = 45
Thread-3: 3 * 0 = 0
Thread-3: 3 * 1 = 3
Thread-3: 3 * 2 = 6
Thread-3: 3 * 3 = 9
Thread-3: 3 * 4 = 12
Thread-3: 3 * 5 = 15
Thread-3: 3 * 6 = 18
Thread-3: 3 * 7 = 21
Thread-3: 3 * 8 = 24
Thread-3: 3 * 9 = 27
Thread-1: 1 * 0 = 0
Thread-8: 8 * 0 = 0
Thread-6: 6 * 0 = 0
Thread-4: 4 * 0 = 0
Thread-2: 2 * 0 = 0
Thread-4: 4 * 1 = 4
Thread-6: 6 * 1 = 6
Thread-8: 8 * 1 = 8
Thread-8: 8 * 2 = 16
Thread-8: 8 * 3 = 24
Thread-8: 8 * 4 = 32
Thread-8: 8 * 5 = 40
Thread-8: 8 * 6 = 48
Thread-8: 8 * 7 = 56
Thread-8: 8 * 8 = 64
Thread-8: 8 * 9 = 72
Thread-1: 1 * 1 = 1
Thread-1: 1 * 2 = 2
Thread-1: 1 * 3 = 3
Thread-1: 1 * 4 = 4
Thread-1: 1 * 5 = 5
Thread-1: 1 * 6 = 6
Thread-1: 1 * 7 = 7
Thread-1: 1 * 8 = 8
Thread-1: 1 * 9 = 9
Thread-9: 9 * 7 = 63
Thread-6: 6 * 2 = 12
Thread-4: 4 * 2 = 8
Thread-2: 2 * 1 = 2
Thread-4: 4 * 3 = 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-9: 9 * 8 = 72
Thread-4: 4 * 4 = 16
Thread-2: 2 * 2 = 4
Thread-4: 4 * 5 = 20
Thread-4: 4 * 6 = 24
Thread-4: 4 * 7 = 28
Thread-4: 4 * 8 = 32
Thread-4: 4 * 9 = 36
Thread-9: 9 * 9 = 81
Thread-2: 2 * 3 = 6
Thread-2: 2 * 4 = 8
Thread-2: 2 * 5 = 10
Thread-2: 2 * 6 = 12
Thread-2: 2 * 7 = 14
Thread-2: 2 * 8 = 16
Thread-2: 2 * 9 = 18
Thread类有可以存储线程信息所需的所有属性。Java虚拟机使用线程优先级来每个时刻调度一个线程来使用CPU,并且根据线程的情况来设置其每个线程的状态。
如果没有设置线程的名称,Java虚拟机会使用这种格式来时分配一个名称,Thread-XX,其中XX是一个数字。我们不能修改线程的ID以及线程的状态。Thread类也没有实现setId()和setStatus()方法,以允许做出这些修改。
永无止境
在本节,我们学习了如何使用Thread对象来访问线程信息。其实,Runnable的实现类也运行我们访问这些信息。Thread类的静态方法currentThread()可以获取正在执行的Runnable实现类的对象,进而访问线程的信息。需要注意的是,如果尝试设置1到10以外的优先级,setPriority()会抛出名为IllegalArgumentException的异常,
拿来主义
本文是从 《Java 7 Concurrency Cookbook》 (D瓜哥窃译为 《Java7并发示例集》 )翻译而来,仅作为学习资料使用。没有授权,不得用于任何商业行为。小有所成
Calculator类的完整代码
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); } }
}
Test类的完整代码
package com.ysk.demo2;import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Test {
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();
}
}
/**
* 将一个线程的状态输出到一个文件中。
*
* @param pw PrintWriter对象
* @param thread 需要输出状态的线程对象
* @param state 线程的旧状态
*/
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");
}
}
总结
1.线程一共分为以下状态:新建,运行,阻塞,等待,限时等待,终止等6个状态。2.每个线程有唯一ID,通过getState()方法可以获取线程运行状态,getName()获取线程名称,setPriority()设置线程优先级,默认为5,范围为(1-10)。
3.线程优先级并不能决定哪个线程先执行,只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
相关文章推荐
- [Java并发编程]-二、线程信息获取与设置
- Java并发学习之二——获取和设置线程信息
- 并发编程--线程信息的获取与设置
- Java并发学习之二——获取和设置线程信息
- Java并发编程示例(二):获取和设置线程信息
- Java并发编程的艺术(九)——批量获取多条线程的执行结果
- Java并发编程示例(八):处理线程的非受检异常
- Java并发编程示例(五):线程休眠与恢复
- java学习总结——线程信息获取和设置
- 【并发编程】通过命令行获取线程信息
- java多线程编程获取线程返回值:ExecutorCompletionService
- 【Java并发编程】之二:线程中断(含代码)
- 获取java线程中信息
- (五)线程--定制线程及设置和获取线程的优先级别(示例下载)
- (38)21.3.8 线程本地存储---Java编程思想之并发笔记
- 【Java并发编程】之四:守护线程与线程阻塞的四种情况
- 【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
- Java 并发:获取线程的返回值
- Java 获取当前线程的相关信息
- 快速获取java中的内存和线程信息(MBean)