Table of contents


本文是關於併行處理,多工處理(Multi Threads)的相關議題。

Process v.s Thread

Process(行程)擁有各自獨立的記憶體空間,不能與其他process共享,而Thread間可以共享記憶體。Process所使用的資源(memory, CPU time)由作業系統直接分配。

Java對Concurrency語法上的支援

synchronized

宣告在synchronized block的程式,保證同時只有一個threaad會存取

volatile

宣告 volatile (揮發性) 的變數,java保證會讀到最新狀態的變數

善用Immutable的物件來確保程式是ThreadSafe的

任務管理

毫無限制的使用thread,通常會帶來更大的效能問題,如果需要用到較多的threads時,就必須對thread進行管理,決定 那些threads執行順序、同時執行的數量、thread的重用等,也就是進行任務管理。

Thread注意事項
  • 採用多個thread不建得會帶來更高的效益
  • 建立thread的動作很耗資源,反而可能成為效能上的瓶頸
  • 建立過多thread,CPU需花更多的時間做thread的切換跟管理,甚至可能使用超過預期的記憶體數量

Executor

要進行任務管理,我們的thread就不能像這樣簡單的直接執行了 new Thread(runnable).start(); 而是要透過 Executor

    public interface Executor { 
      void execute(Runnable command);
    }

Executor只有定義出實作的類別要可以執行Runnable的method,如果需要知道Executor的生命周期資訊,可以用java.util.concurrent.ExecutorService

concurrency_101_001.png

Executor的會依execution policy(執行政策)的不同會許多的實作,java.util.concurrent內建的execution policy可參閱上圖。 java.util.concurrent package裡有一個java.util.concurrent.Executors提供許多factory methods來建立executor.

concurrency_101_002.png

    Executor executionPolicy = Executors.newFixedThreadPool(5);
    executionPolicy.execute(runnable)

如果需要更多的彈性,可以直接使用ThreadPoolExecutor,而不是透過Executor

        /**
         * Creates a new {@code ThreadPoolExecutor} with the given initial
         * parameters.
         *
         * @param corePoolSize the number of threads to keep in the pool, even
         *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
         * @param maximumPoolSize the maximum number of threads to allow in the
         *        pool
         * @param keepAliveTime when the number of threads is greater than
         *        the core, this is the maximum time that excess idle threads
         *        will wait for new tasks before terminating.
         * @param unit the time unit for the {@code keepAliveTime} argument
         * @param workQueue the queue to use for holding tasks before they are
         *        executed.  This queue will hold only the {@code Runnable}
         *        tasks submitted by the {@code execute} method.
         * @param threadFactory the factory to use when the executor
         *        creates a new thread
         * @param handler the handler to use when execution is blocked
         *        because the thread bounds and queue capacities are reached
         * @throws IllegalArgumentException if one of the following holds:<br>
         *         {@code corePoolSize < 0}<br>
         *         {@code keepAliveTime < 0}<br>
         *         {@code maximumPoolSize <= 0}<br>
         *         {@code maximumPoolSize < corePoolSize}
         * @throws NullPointerException if {@code workQueue}
         *         or {@code threadFactory} or {@code handler} is null
         */
        public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler)

Resource