应用工厂模式,进行对象实例化有如下优点:
- 可以简单的改变对象实例化的类或者对象实例化的方式。
- 可以为有限的资源简单的限制对象的创建。例如,给定一个类型,限定其只有n个对象。
- 可以简单的生成对象实例化的统计数据。
Java提供了ThreadFactory接口,用来实现线程对象工厂。一些Java并发API中的高级函数使用线程工厂创建线程。
在本节中,将会学到如何实现ThreadFactory接口来创建个性化名称的线程对象,同事保存创建的线程对象的统计信息。
准备工作
本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。
实现过程
通过如下步骤完成范例:
-
创建名为MyThreadFactory的类,指定其实现ThreadFactory接口:
public class MyThreadFactory implements ThreadFactory {
-
定义三个属性:名为counter的整型,用来存储创建的线程对象个数;名为name的字符串,存储创建的每个线程的基本名字;名为stats的字符串队列,用来保存创建的线程对象统计数据。同时,实现类的构造函数,初始化这些属性:
private int counter; private String name; private List<String> stats; public MyThreadFactory(String name){ counter = 0; this.name = name; stats = new ArrayList<String>(); }
-
实现newThread()方法。这个方法会接受Runnable接口,为这个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 %s\n", t.getId(), t.getName(), new Date())); return t; }
-
实现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(); }
-
创建名为Task的类,指定其实现Runnable接口。在本范例中,这些任务只休眠1秒钟,不做任何操作:
public class Task implements Runnable{ @Override public void run() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }
-
创建范例的主类,创建名为Main的类并实现main()方法:
public class Main { public static void main(String[] args) {
-
创建MyThreadFactory和Task对象:
MyThreadFactory factory = new MyThreadFactory("MyThreadFactory"); Task task = new Task();
-
使用MyThreadFactory对象创建10个Thread对象,然后启动这些线程:
Thread thread; System.out.printf("Starting the Threads\n"); for(int i = 0 ; i < 10 ; i ++){ thread = factory.newThread(task); thread.start(); }
-
将线程工厂的统计信息输出到控制台:
System.out.printf("Factory stats: \n"); System.out.printf("%s\n", factory.getStats());
-
运行程序,查看结果。
工作原理
ThreadFactory接口只有一个方法,称为newThread()。此方法参数为Runnable对象,返回一个线程对象。当实现ThreadFactory接口时,需要重写newThread方法。最基本的ThreadFactory写法只有一行代码:
可以通过增加一些转化来改进接口实现,如下所示:
- 例如本范例中,通过使用特殊格式的名字,甚至不需要继承Java Thread类创建个性化的线程;
- 保存线程的创建统计信息;
- 限定创建的线程数量;
- 确定线程的创建。
ThreadFactory接口可以增加所有你能想到的变化。使用工厂模式是很好的编程实践,但是如果实现ThreadFactory接口用来集中管理线程创建,就必须检查代码以确保所有创建的线程使用相同的工厂。
更多关注
- 第8章“定制并发类”中“实现ThreadFactory接口生成定制化线程”和“执行对象中使用ThreadFactory接口”小节