使用工厂创建线程

工厂模式是最常使用的设计模式之一。 它是一构建模式,目标是开发一个对象,该对象的任务是创建其他一个或多个类的对象。 这样当我们想创建一个那些类的对象时,使用工厂,而不是 new 操作符。

使用工厂创建对象有几个好处:

  • 能比较容易修改被创建对象的类或创建这些对象的方式
  • 容易限制需要受限资源的对象的创建。例如一个类型只能创建N个对象。
  • 容易生成关于对象的创建的统计数据

Java 提供了 ThreadFactory 接口来实现线程对象工厂。Java concurrency API 的一些辅助类使用线程工厂来创建线程。

任务

实现 ThreadFactory 接口来创建有自己的名字的线程,同时保存所创建线程对象的统计数据。

实现

  • 线程工厂类 (MyThreadFactory)

    • 实现 ThreadFactory 接口
    public class MyThreadFactory implements ThreadFactory
    
    • 声明 3 个属性并实现构造函数
      • 整型的 counter: 用来存储创建的线程对象的个数
      • String类型的 name : 每个线程的基准名称
      • List<String> 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 接口,为此接口返回一个 Thread 对象。 在本例的此方法中,生成线程对象的名字,创建新的的线程对象并保存统计数据。
        @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 getStatistics() {
            StringBuffer buffer = new StringBuffer();
            for (String stat : stats) {
                buffer.append(stat);
                buffer.append("\n");
            }
            return buffer.toString();
        }
    
  • 控制类 (Main)

    • 创建 MyThreadFactory 和 Task 对象
            MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");
            Task task = new Task();
    
    • 使用 MyThreadFactory 对象创建多个线程并启动它们
            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.getStatistics());
    

工作原理

ThreadFactory 接口只有一个名为 newThread 的方法。它的参数是一个 Runnable 对象,返回一个 Thread 对象。 最基本的线程工厂的该方法只由一行:

return new Thread(r);

您可以让它更精彩,例如:

  • 创建个性化的线程,如名称有特定格式,甚至创建您自己的Java Thread 类的继承类
  • 保存线程创建的统计信息
  • 限制创建的线程的数量
  • 校验线程的创建结果
  • 其他等等

使用工厂设计模式是一个好的编程习惯。 不过如果您实现一个 ThreadFactory 接口来集中创建线程,您也得复查代码来保证所有线程都是使用此工厂来创建。