当前位置: 移动技术网 > IT编程>开发语言>Java > Java并发编程示例(十):线程组

Java并发编程示例(十):线程组

2019年07月22日  | 移动技术网IT编程  | 我要评论

对线程分组是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();
            }
        }
    }
}


如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网