ThreadPoolExecutor的构造函数接受一个参数,是ThreadFactory,这是一个用于创建线程的工厂。工厂模式做为Java各种框架中使用最频繁的一种设计模式,所以下面好好讲讲这一内容。

从例子开始

工厂模式是设计模式中最简单,最容易理解的一种模式,因为它是和现实直接挂勾,是对现实的直接模拟。举一个例子,假如,现在有一个工厂,可以生产鼠标,键盘,摄像头。做为顾客,要从这个工厂中获得具体的产品,我们其实是不想知道这些产品在工厂中是如何被创建的。我们所希望的是,通过这个工厂的一个接口,就可以获得这些产品。

我们先定义键盘如下:

public interface Device {
    void setModel(int model);
    int getModel();

    void setSize(int size);
    int getSize();
}

class KeyBoard implements Device {
    int model;
    int size;

    @Override
    public void setModel(int model) {
        this.model = model;
    }

    @Override
    public int getModel() {
        return model;
    }

    @Override
    public void setSize(int size) {
        this.size = size;
    }

    @Override
    public int getSize() {
        return size;
    }
}

鼠标和摄像头也是同样的定义,这里就不再列出了。如果,我们使用这个定义来写代码,就要这样写:

Device d = new KeyBoard();
        d.setModel(1);
        d.setSize(5);

看上去好像还可以,但如果,将来keyBoard的定义发生改变了,比如增加一个字段,来表示keyBoard是不是机械键盘,那么所有使用KeyBoard的构造函数的地方,都要修改,这肯定是很不好的,所以,我们可以想办法,把这些东西封装起来。

这里要介绍的方法就是工厂方法。我们可以通过在中间引入一层抽象。做为客户端我们只要去访问这个中间层的特定方法就好了。例如:


public class DeviceFactory {
    public Device getProduct(String name) {
        if (name.equals("keyboard")) {
            Device d = new KeyBoard();
            d.setModel(1);
            d.setSize(5);
            return d;
        }
        else if (name.equals("mouse")) {
            return new Mouse();
        }
        else if (name.equals("camera")) {
            return new Camera();
        }
        else
            return null;
    }
}

    // 客户端程序
    public static void main(String[] args) {
        DeviceFactory factory = new DeviceFactory();
        KeyBoard keyBoard = (KeyBoard) factory.getProduct("keyboard");
    }

即使将来,KeyBoard的定义发生了变化,我们不必修改客户端程序。KeyBoard的生产流程,工厂去关心就好了,做为用户,我们就不应该关心:

lass KeyBoard implements Device {
    int model;
    int size;
    boolean isMechanical;

    //....其他定义略去
    public void setMechanical(boolean isMechanical) {
        this.isMechanical = isMechanical;
    }
}

相应的工厂变成这样:

public class DeviceFactory {
    public Device getProduct(String name) {
        if (name.equals("keyboard")) {
            KeyBoard d = new KeyBoard();
            d.setModel(1);
            d.setSize(5);
            d.setMechanical(true);
            return d;
        }
        //...其他略去
    }
}

通过这一层抽象,我们就把客户端与具体的产品建造过程分隔开了。这种模式就是工厂模式。总结一下,工厂模式就是引入一个工厂类,由它来负责某些具体类的创建和构造。


ThreadFactory

昨天我们讲到了ThreadFactory,我们来看一下JDK源码,在知道了工厂模式之后,这种命名,以及它们的结构,就毫无秘密可言了:

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

这里使用了defaultThreadFactory做为参数,那我们继续看defaultThreadFactory是什么样的:



public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }

    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

很显然,newThread方法就是这个工厂类的工厂方法,真正创建线程的地方就在这里。


比如说,如果我们现在希望使用一个线程池,这个线程池里的线程的调度优先级变高或者变低,那么我们就只需要重新定义一个线程工厂,在工厂方法中把线程的优先级调高或者调低就可以了。