线程组
Java并发 API里有个有趣的方法是把线程分组。这个方法允许我们按线程组作为一个单位来处理。例如,你有一些线程做着同样的任务,你想控制他们,无论多少线程还在运行,他们的状态会被一个call 中断。
Java 提供 ThreadGroup 类来组织线程。 ThreadGroup 对象可以由 Thread 对象组成和由另外的 ThreadGroup 对象组成,生成线程树结构。
在这个指南中, 我们将开发一个简单的例子来学习 ThreadGroup 对象。我们有 10 个随机时间休眠的线程 (例如,模拟搜索),然后当其中一个完成,就中断其余的。
准备
指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。
怎么做呢…
按照这些步骤来实现下面的例子::
1. 首先,创建一个类名为 Result。它会保存最先结束的线程的名字。声明一个 private String 属性名为 name 并提供相应的读值和设置值的方法。
2. 创建一个类名为 SearchTask a并一定实现 Runnable 接口。
1 |
public class SearchTask implements Runnable { |
3. 声明一个Result类的 private 属性变量并实现和初始化这类属性的构造函数。
2 |
public SearchTask(Result result) { |
4. 实现run()方法。 它会调用doTask() 方法和等待它结束或者接收一个 InterruptedException 异常。 这方法会写信息表明开始,结束,或者线程中断。
03 |
String name=Thread.currentThread().getName(); |
04 |
System.out.printf( "Thread %s: Start\n" ,name); |
08 |
} catch (InterruptedException e) { |
09 |
System.out.printf( "Thread %s: Interrupted\n" ,name); |
12 |
System.out.printf( "Thread %s: End\n" ,name); |
5. 实现 doTask() 方法。它会创建一个 Random 对象生一个随机数字并用这个数字调用 sleep() 方法 。
1 |
private void doTask() throws InterruptedException { |
2 |
Random random= new Random(( new Date()).getTime()); |
3 |
int value=( int )(random.nextDouble()* 100 ); |
4 |
System.out.printf( "Thread %s: %d\n" ,Thread.currentThread(). getName(),value); |
5 |
TimeUnit.SECONDS.sleep(value); |
6. 现在, 创建例子主类通过创建 Main 类和实现 main() 方法.
2 |
public static void main(String[] args) { |
7. 首先, 创建一个 ThreadGroup 对象命名 Searcher.
1 |
ThreadGroup threadGroup = new ThreadGroup( "Searcher" ); |
8. 然后, 创建 一个 SearchTask 对象和 一个 Result 对象。
1 |
Result result= new Result(); |
2 |
SearchTask searchTask= new SearchTask(result); |
9. 现在, 使用SearchTask对象创建 10个 Thread o对象。当你调用Thread 类的构造函数时,传递它作为ThreadGroup对象的第一个参数。
1 |
for ( int i= 0 ; i< 5 ; i++) { |
2 |
Thread thread= new Thread(threadGroup, searchTask); |
5 |
TimeUnit.SECONDS.sleep( 1 ); |
6 |
} catch (InterruptedException e) { |
10. 使用list() 方法写关于 ThreadGroup ob对象信息。
2 |
System.out.printf( "Information about the Thread Group\n" ); |
11. 使用 activeCount() 和 enumerate() 方法来获取线程个数和与ThreadGroup对象关联的线程的列表。我们可以用这个方法来获取信息, 例如,每个线程状态。
1 |
Thread[] threads= new Thread[threadGroup.activeCount()]; |
2 |
threadGroup.enumerate(threads); |
3 |
for ( int i= 0 ; i<threadGroup.activeCount(); i++) { |
4 |
System.out.printf( "Thread %s: %s\n" ,threads[i].getName(),threads[i].getState()); |
12. 调用 waitFinish()方法. 我们等下来实现这方法。它会等待ThreadGroup对象中的其中一个线程结束。
1 |
waitFinish(threadGroup); |
13. 用interrupt() 方法中断组里的其他线程。
1 |
threadGroup.interrupt(); |
14. 实现 waitFinish() 方法. 它会使用 activeCount() 方法来控制到最后一个线程。
1 |
private static void waitFinish(ThreadGroup threadGroup) { |
2 |
while (threadGroup.activeCount()> 9 ) { |
4 |
TimeUnit.SECONDS.sleep( 1 ); |
5 |
} catch (InterruptedException e) { |
15. 运行例子并查看结果。
它是怎么工作的…
在下面的截图内, 你可以发现 list() 方法 的输出和当我们把每个线程对象的状态写入时候的输出, 请看截图:
ThreadGroup 类储存线程对象和其他有关联的 ThreadGroup 对象,所以它可以访问他们的所有信息 (例如,状态) 和全部成员的操作表现 (例如,中断)。
更多…
ThreadGroup 类有很多方法. 查看 API 文档里的这些方法的详细说明。