本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.13节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.13 使用工厂类创建线程
工厂模式是面向对象编程中最常使用的模式之一。它是一个创建者模式,使用一个类为其他的一个或者多个类创建对象。当我们要为这些类创建对象时,不需再使用new构造器,而使用工厂类。
使用工厂类,可以将对象的创建集中化,这样做有以下的好处:
◆ 更容易修改类,或者改变创建对象的方式;
◆ 更容易为有限资源限制创建对象的数目。例如,我们可以限制一个类型的对象不多于n个。
◆ 更容易为创建的对象生成统计数据。
Java提供了ThreadFactory接口,这个接口实现了线程对象工厂。Java并发API的高级工具类也使用了线程工厂创建线程。
在本节中,我们将学习如何通过实现ThreadFactory接口来创建线程对象,用以生成个性化名称的线程并且保存这些线程对象的统计信息。
准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。
范例实现
按照接下来的步骤实现本节的范例。
1.创建名为MyThreadFactory的类,并且实现ThreadFactory接口。
``
public class MyThreadFactory implements ThreadFactory {``
2.声明3个属性:整型数字counter,用来存储线程对象的数量;字符串name,用来存放每个线程的名称;字符串列表stats,用来存放线程对象的统计数据。同时实现带参数的构造器来初始化这3个属性。
private int counter;
private String name;
private List<String> stats;
public MyThreadFactory(String name){
counter=0;
this.name=name;
stats=new ArrayList<String>();
}```
3.实现newThread()方法。这个方法以Runnable接口对象为参数,并且返回参数对应的线程对象。这里我们创建一个线程对象并生成线程名称,保存统计数据。
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r,name+"-Thread_"+counter);
counter++;
stats.add(String.format("Created thread %d with name %s on %sn",t.getId(),t.getName(),new Date()));
return t;
}`
4.实现getStatistics()方法,返回一个字符串对象,用来表示所有线程对象的统计数据。
public String getStats(){
StringBuffer buffer=new StringBuffer();
Iterator<String> it=stats.iterator();
while (it.hasNext()) {
buffer.append(it.next());
buffer.append("\n");
}
return buffer.toString();
}```
5.创建名为Task的类并且实现Runnable接口。在这个范例中,线程除了只休眠1秒钟之外,不做任何事情。
public class Task implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}`
6.创建范例的主程序。创建一个包含main()方法的主类Main。
public class Main {
public static void main(String[] args) {```
7.创建一个MyThreadFactory对象,创建一个Task对象。
MyThreadFactory factory=new MyThreadFactory("MyThreadFactory");
Task task=new Task();`
8.使用工厂类MyThreadFactory创建10个线程对象,并且启动它们。
Thread thread;
System.out.printf("Starting the Threads\n");
for (int i=0; i<10; i++){
thread=factory.newThread(task);
thread.start();
}```
9.将线程工厂的统计打印到控制台。
System.out.printf("Factory stats:n");
System.out.printf("%sn",factory.getStats());`
10.运行范例并且查看运行结果。
工作原理
ThreadFactory接口只有一个方法,即newThread,它以Runnable接口对象作为传入
参数并且返回一个线程对象。当实现ThreadFactory接口时,必须实现覆盖这个方法。大多数基本的线程工厂类只有一行,即:
``
return new Thread(r);``
可以通过增加一些变化来强化实现方法覆盖。
◆ 创建一个个性化线程,如本范例使用一个特殊的格式作为线程名,或者通过继承Thread类来创建自己的线程类;
◆ 保存新创建的线程的统计数据,如本节的范例那样;
◆ 限制创建的线程的数量;
◆ 对生成的线程进行验证;
◆ 更多你可以想到的。
使用工厂设计模式是一个很好的编程实践,但是,如果是通过实现ThreadFactory接口来创建线程,你必须检查代码,以保证所有的线程都是使用这个工厂创建的。