1. 程式人生 > >java.util.concurrent.ThreadFactory 例項講解

java.util.concurrent.ThreadFactory 例項講解

本文到例項中將講解一下如何使用ThreadFactory介面。這個介面是Java自身提供的,使用者可以實現它自定義自己的執行緒啟動方式,可以設定執行緒名稱、型別以及優先順序等屬性。

ThreadFactory vs Default ThreadFactory:
在一個典型的Java ExecutorService程式中,其執行緒都需要被指定以何種形式執行,如果程式初始化ExecutorService時沒有指定ThreadFactory,程式會採用一個預設的ThreadFactory來生成提交執行緒,但是對於一個嚴謹對程式來說,定義自己的ThreadFactory永遠是個最佳選擇。Why??

  1. 設定更有描述意義的執行緒名稱。如果使用預設的ThreadFactory,它給執行緒起名字大概規律就是pool-m-thread-n這個樣子,如pool-1-thread-1。但是當你分析一個thread dump時,看著這樣的名字就很難知道執行緒的目的。所以使用一個有描述意義的執行緒名稱是分析追蹤問題的clue NO.1。
  2. 設定執行緒是否是守護執行緒,預設的ThreadFactory總是提交非守護執行緒
  3. 設定執行緒優先順序,預設ThreadFactory總是提交的一般優先順序執行緒

例子:
CustomThreadFactoryBuilder類實現了一種優雅的Builder Mechanism

方式去得到一個自定義ThreadFactory例項。ThreadFactory介面中有一個接受Runnable型別引數的方法newThread(Runnable r),你自己的factory邏輯就應該寫在這個方法中,去配置執行緒名稱、優先順序、守護執行緒狀態等屬性。

public class CustomThreadFactoryBuilder {

    private String namePrefix = null;
    private boolean daemon = false;
    private int priority = Thread.NORM_PRIORITY;

    public
CustomThreadFactoryBuilder setNamePrefix(String namePrefix) { if (namePrefix == null) { throw new NullPointerException(); } this.namePrefix = namePrefix; return this; } public CustomThreadFactoryBuilder setDaemon(boolean daemon) { this.daemon = daemon; return this; } public CustomThreadFactoryBuilder setPriority(int priority) { if (priority < Thread.MIN_PRIORITY){ throw new IllegalArgumentException(String.format( "Thread priority (%s) must be >= %s", priority, Thread.MIN_PRIORITY)); } if (priority > Thread.MAX_PRIORITY) { throw new IllegalArgumentException(String.format( "Thread priority (%s) must be <= %s", priority, Thread.MAX_PRIORITY)); } this.priority = priority; return this; } public ThreadFactory build() { return build(this); } private static ThreadFactory build(CustomThreadFactoryBuilder builder) { final String namePrefix = builder.namePrefix; final Boolean daemon = builder.daemon; final Integer priority = builder.priority; final AtomicLong count = new AtomicLong(0); /* return new ThreadFactory() { @Override public Thread newThread(Runnable runnable) { Thread thread = new Thread(runnable); if (namePrefix != null) { thread.setName(namePrefix + "-" + count.getAndIncrement()); } if (daemon != null) { thread.setDaemon(daemon); } if (priority != null) { thread.setPriority(priority); } return thread; } };*/ //jdk8中還是優先使用lamb表示式 return (Runnable runnable) -> { Thread thread = new Thread(runnable); if (namePrefix != null) { thread.setName(namePrefix + "-" + count.getAndIncrement()); } if (daemon != null) { thread.setDaemon(daemon); } /* thread.setPriority(priority); */ return thread; }; } }

SimpleTask類實現類Runnable介面,打印出了執行緒的執行屬性(名稱,優先順序等)。

public class SimpleTask implements Runnable {
    private long sleepTime;

    public SimpleTask(long sleepTime) {
        super();
        this.sleepTime = sleepTime;
    }

    @Override
    public void run() {
        while (true) {
            try {
                System.out.println("Simple task is running on " 
                        + Thread.currentThread().getName() + " with priority " + Thread.currentThread().getPriority());
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

CustomThreadFactoryDemo類使用我們上面的CustomThreadFactoryBuilder類建立類一個ThreadFactory例項,又使用這個例項獲得類一個ExecutoryService,這樣所有這個執行緒池中的執行緒都會按我們定義好的屬性被生成,下面程式碼中執行類三個SimpleTask。

public class CustomThreadFactoryDemo {

    public static void main(String[] args) {

        ThreadFactory customThreadfactory = new CustomThreadFactoryBuilder()
        .setNamePrefix("DemoPool-Thread").setDaemon(false)
        .setPriority(Thread.MAX_PRIORITY).build();

        ExecutorService executorService = Executors.newFixedThreadPool(3,
        customThreadfactory);

        // Create three simple tasks with 1000 ms sleep time
        SimpleTask simpleTask1 = new SimpleTask(1000);
        SimpleTask simpleTask2 = new SimpleTask(1000);
        SimpleTask simpleTask3 = new SimpleTask(1000);

        // Execute three simple tasks with 1000 ms sleep time
        executorService.execute(simpleTask1);
        executorService.execute(simpleTask2);
        executorService.execute(simpleTask3);

    }

}

輸出:

Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10