Java并发编程示例(十):线程组
对线程分组是java并发api提供的一个有趣功能。我们可以将一组线程看成一个独立单元,并且可以随意操纵线程组中的线程对象。比如,可以控制一组线程来运行同样的任务,无需关心有多少线程还在运行,还可以使用一次中断调用中断所有线程的执行。
java提供了threadgroup类来控制一个线程组。一个线程组可以通过线程对象来创建,也可以由其他线程组来创建,生成一个树形结构的线程。
根据《effective java》的说明,不再建议使用threadgroup。建议使用executor。
——d瓜哥特此说明。
在本节,我们就使用threadgroup来开发一个简单的示例。我们将创建十个休眠时间不等的线程(比如模拟搜索),当其中一个完成时,中断其余线程。
知其然
按照下面所示步骤,完成示例代码。
1.创建一个名为result的类,用于存储第一个完成任务的线程的名字。声明一个string类型的私有变量,name,同时生成setter/getter方法。代码如下:
public class result {
private string name;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
}
2.创建一个名为searchtask的类,并实现runnable接口。代码如下:
public class searchtask implements runnable {
3.声明一个result类型的私有变量,并通过构造函数来实例化该变量。代码如下:
private result result;
public searchtask(result result) {
this.result = result;
}
4.实现run()方法,在其中调用dotask()方法,来等待完成或被中断。该方法还向控制台打印信息来显示线程的开始、结束或者中断。代码如下:
@override
public void run() {
string name = thread.currentthread().getname();
system.out.printf("thread %s: start\n", name);
try {
dotask();
result.setname(name);
} catch (interruptedexception e) {
system.out.printf("thread %s: interrupted\n", name);
return;
}
system.out.printf("thread %s: end\n", name);
}
5.实现dotask()方法,该方法将创建一个random对象,然后使用该对象生成一个随机数,来调节线程休眠的时间。代码如下:
// 模拟搜索
private void dotask() throws interruptedexception {
random random = new random(new date().gettime());
int value = (int) (random.nextdouble() * 100);
system.out.printf("thread %s: %d\n",
thread.currentthread().getname(), value);
timeunit.seconds.sleep(value);
}
6.创建示例程序的主类,main,并实现main()方法。代码如下:
public class main {
public static void main(string[] args) {
7.创建一个名称为searcher的threadgroup对象。代码如下:
threadgroup threadgroup = new threadgroup("searcher");
8.然后,创建一个result对象和searchtask对象。代码如下:
result result = new result();
searchtask searchtask = new searchtask(result);
9.searchtask对象使用创建十个thread对象,并且创建thread对象时,将threadgroup对象作为第一个参数,传递给thread类的构造函数。代码如下:
for (int i = 0; i < 5; i++) {
thread thread = new thread(threadgroup, searchtask);
thread.start();
try {
timeunit.seconds.sleep(1);
} catch (interruptedexception e) {
e.printstacktrace();
}
}
10.使用list()方法将threadgroup对象的信息打印出来。代码如下:
system.out.printf("number of threads: %d\n", threadgroup.activecount());
system.out.println("information about the thread group");
threadgroup.list();
11.使用activecount()和enumerate()来获取threadgroup对象中的活跃线程数并将其复制到一个线程数组中。使用get*()方法,获取线程的名称和状态。代码如下:
thread[] threads = new thread[threadgroup.activecount()];
threadgroup.enumerate(threads);
for (int i = 0; i < threadgroup.activecount(); i++) {
system.out.printf("thread %s: %s\n", threads[i].getname(),
threads[i].getstate());
}
12.调用waitfinish()方法,等待threadgroup对象中的其中一个线程完成任务。稍后实现该方法。代码如下:
waitfinish(threadgroup);
13.使用interrupt()方法,中断线程组中其他线程。代码如下:
threadgroup.interrupt();
14.实现waitfinish()方法,使用activecount()方法控制线程的执行结果。代码如下:
// 等待任务完成
private static void waitfinish(threadgroup threadgroup) {
while (threadgroup.activecount() > 9) {
try {
timeunit.seconds.sleep(1);
} catch (interruptedexception e) {
e.printstacktrace();
}
}
}
15.运行程序,查看执行效果。
知其所以然
下面是程序执行的结果。你将看到list()方法的输出,各个线程的状态等。
thread thread-0: start
thread thread-0: 52
thread thread-1: start
thread thread-1: 41
thread thread-2: start
thread thread-2: 69
thread thread-3: start
thread thread-3: 60
thread thread-4: start
thread thread-4: 88
number of threads: 5
information about the thread group
java.lang.threadgroup[name=searcher,maxpri=10]
thread[thread-0,5,searcher]
thread[thread-1,5,searcher]
thread[thread-2,5,searcher]
thread[thread-3,5,searcher]
thread[thread-4,5,searcher]
thread thread-0: timed_waiting
thread thread-1: timed_waiting
thread thread-2: timed_waiting
thread thread-3: timed_waiting
thread thread-4: timed_waiting
thread thread-1: interrupted
thread thread-4: interrupted
thread thread-2: interrupted
thread thread-0: interrupted
thread thread-3: interrupted
threadgroup类保存着众多thread对象以及关联的threadgroup对象。可以通过调用该类的方法,访问线程的信息,还可以对其进行各种操作,比如中断等。
永无止境
threadgroup类还有好多方法。请翻阅api文档,查看完整的方法说明。
拿来主义
本文是从 《java 7 concurrency cookbook》 (d瓜哥窃译为 《java7并发示例集》 )翻译而来,仅作为学习资料使用。没有授权,不得用于任何商业行为。
小有所成
下面是本节示例所用的代码的完整版。
result类的完整代码:
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
/**
* 存储查询结果
* date: 2013-09-30
* time: 00:45
*/
public class result {
private string name;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
}
searchtask类的完整代码
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.date;
import java.util.random;
import java.util.concurrent.timeunit;
/**
* 模拟搜索类
* date: 2013-10-02
* time: 22:38
*/
public class searchtask implements runnable {
private result result;
public searchtask(result result) {
this.result = result;
}
@override
public void run() {
string name = thread.currentthread().getname();
system.out.printf("thread %s: start\n", name);
try {
dotask();
result.setname(name);
} catch (interruptedexception e) {
system.out.printf("thread %s: interrupted\n", name);
return;
}
system.out.printf("thread %s: end\n", name);
}
// 模拟搜索
private void dotask() throws interruptedexception {
random random = new random(new date().gettime());
int value = (int) (random.nextdouble() * 100);
system.out.printf("thread %s: %d\n",
thread.currentthread().getname(), value);
timeunit.seconds.sleep(value);
}
}
main类的完整代码:
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.concurrent.timeunit;
/**
* 线程组示例主类
* date: 2013-10-02
* time: 22:45
*/
public class main {
public static void main(string[] args) {
threadgroup threadgroup = new threadgroup("searcher");
result result = new result();
searchtask searchtask = new searchtask(result);
for (int i = 0; i < 5; i++) {
thread thread = new thread(threadgroup, searchtask);
thread.start();
try {
timeunit.seconds.sleep(1);
} catch (interruptedexception e) {
e.printstacktrace();
}
}
system.out.printf("number of threads: %d\n", threadgroup.activecount());
system.out.println("information about the thread group");
threadgroup.list();
thread[] threads = new thread[threadgroup.activecount()];
threadgroup.enumerate(threads);
for (int i = 0; i < threadgroup.activecount(); i++) {
system.out.printf("thread %s: %s\n", threads[i].getname(),
threads[i].getstate());
}
waitfinish(threadgroup);
threadgroup.interrupt();
}
// 等待任务完成
private static void waitfinish(threadgroup threadgroup) {
while (threadgroup.activecount() > 9) {
try {
timeunit.seconds.sleep(1);
} catch (interruptedexception e) {
e.printstacktrace();
}
}
}
}
推荐阅读
-
Java并发编程示例(十):线程组
-
Java并发编程示例(六):等待线程执行终止
-
Java并发编程示例(七):守护线程的创建和运行
-
java线程并发blockingqueue类使用示例
-
多线程编程之卫生间 博客分类: 线程 java线程并发厕所卫生间
-
LockSupport详解 | Java并发编程 博客分类: 线程 LockSupportparkBlockjava并发详解
-
volatile关键字实例分析 博客分类: java并发编程 volatile并发线程javasynchronized
-
04-java并发编程之定时线程池ScheduledThreadPoolExecutor
-
Java并发编程:AtomicInteger&CAS 博客分类: Java多线程 Java并发编程AtomicIntegerCAS
-
Java并发编程:阻塞队列 博客分类: Java多线程 java阻塞队列