Java线程池原理与实例详解

Wiki

采用new Thread的方式产生多线程,可能有以下一些问题:
 线程的创建和销毁开销很大,尤其是有些线程的存在时间较短;
 线程的创建和销毁过程中伴随着CPU在线程间的切换,开销很大;
线程池的优点有:
 减少了创建和销毁线程的次数,工作线程可以一直重用。
在java中,每个线程都归属于某个ThreadGroup来管理。

ThreadGroup源码分析

首先看成员变量。

/**
 * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
 * This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
 * @see Thread
 */
public class ThreadGroup implements Thread.UncaughtExceptionHandler {

    // Name of this ThreadGroup
    // VM needs this field name for debugging.
    private String name;

    // Maximum priority for Threads inside this ThreadGroup
    private int maxPriority = Thread.MAX_PRIORITY;

    // The ThreadGroup to which this ThreadGroup belongs
    // VM needs this field name for debugging.
    final ThreadGroup parent;

    /**
     * Weak references to the threads in this group.
     * Access is guarded by synchronizing on this field.
     */
    private final List> threadRefs = new ArrayList>(5);

    /**
     * View of the threads.
     * Access is guarded by synchronizing on threadRefs.
     */
    private final Iterable threads = CollectionUtils.dereferenceIterable(threadRefs, true);

    /**
     * Thread groups. Access is guarded by synchronizing on this field.
     */
    private final List groups = new ArrayList(3);

    // Whether this ThreadGroup is a daemon ThreadGroup or not
    private boolean isDaemon;

    // Whether this ThreadGroup has already been destroyed or not
    private boolean isDestroyed;

    /* the VM uses these directly; do not rename */
    **static final ThreadGroup systemThreadGroup = new ThreadGroup();
static final ThreadGroup mainThreadGroup = new ThreadGroup(systemThreadGroup, "main");**
……省略代码……
}

ThreadGroup中采用弱引用的链表方式,可以添加Thread(链表默认容量为5)。同时有一个ThreadGroup本身也可以通过链表方式组织其他的ThreadGroup(链表默认容量为3)。
Java线程池原理与实例详解_第1张图片
另外,这里定义了一个main类型的ThreadGroup。也就是说,在主线程的线程组的名字就是“main”。例如:

public class Main {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String name=Thread.currentThread().getThreadGroup().getName();
        System.out.println(name);
    }
}

下面来看ThreadGroup的3构造函数。

/**
 * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
 * This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
 * @see Thread
 */
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
……省略代码……

    /**
     * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup}
     * will be child of the {@code ThreadGroup} to which the calling thread belongs.
     *
     * @param name the name
     * @see Thread#currentThread
     */
    public ThreadGroup(String name) {
        this(Thread.currentThread().getThreadGroup(), name);
    }

    /**
     * Constructs a new {@code ThreadGroup} with the given name, as a child of the
     * given {@code ThreadGroup}.
     *
     * @param parent the parent
     * @param name the name
     * @throws NullPointerException if {@code parent == null}
     * @throws IllegalThreadStateException if {@code parent} has been
     *         destroyed already
     */
    public ThreadGroup(ThreadGroup parent, String name) {
        if (parent == null) {
            throw new NullPointerException("parent == null");
        }
        this.name = name;
        this.parent = parent;
        if (parent != null) {
            parent.add(this);
            this.setMaxPriority(parent.getMaxPriority());
            if (parent.isDaemon()) {
                this.setDaemon(true);
            }
        }
    }

    /**
     * Initialize the special "system" ThreadGroup. Was "main" in Harmony,
     * but we have an additional group above that in Android.
     */
    private ThreadGroup() {
        this.name = "system";
this.parent = null;
    }
……省略代码……
}

如果是完全无参数的构造函数,表明这个ThreadGroup没有parent,否则parent就是生成ThreadGroup的当前线程的线程组。这样,ThreadGroup就可以形成一棵树。
Java线程池原理与实例详解_第2张图片
继续查看ThreadGroup的关键方法。

/**
 * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
 * This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
 * @see Thread
 */
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
……省略代码……
/**
     * Returns the number of running {@code Thread}s which are children of this thread group,
     * directly or indirectly.
     *
     * @return the number of children
     */
    public int activeCount() {
        int count = 0;
        synchronized (threadRefs) {
            for (Thread thread : threads) {
                if (thread.isAlive()) {
                    count++;
                }
            }
        }
        synchronized (groups) {
            for (ThreadGroup group : groups) {
                count += group.activeCount();
            }
        }
        return count;
}
    /**
     * Interrupts every {@code Thread} in this group and recursively in all its
     * subgroups.
     *
     * @see Thread#interrupt
     */
    public final void interrupt() {
        synchronized (threadRefs) {
            for (Thread thread : threads) {
                thread.interrupt();
            }
        }
        synchronized (groups) {
            for (ThreadGroup group : groups) {
                group.interrupt();
            }
        }
    }
……省略代码……
}

由于一个ThreadGroup中的Thread是由链表方式组织的弱引用类型,activeCount()可以返回当前还有效的Thread。interrupt()函数让一个ThreadGroup中所有的Thread都中断。

Thread源码分析

这里主要分析与ThreadGroup相关的内容。
首先看Thread的9个构造函数。

/**
     * Constructs a new {@code Thread} with no {@code Runnable} object and a
     * newly generated name. The new {@code Thread} will belong to the same
     * {@code ThreadGroup} as the {@code Thread} calling this constructor.
     *
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread() {
        create(null, null, null, 0);
    }

    /**
     * Constructs a new {@code Thread} with a {@code Runnable} object and a
     * newly generated name. The new {@code Thread} will belong to the same
     * {@code ThreadGroup} as the {@code Thread} calling this constructor.
     *
     * @param runnable
     *            a {@code Runnable} whose method run will be
     *            executed by the new {@code Thread}
     *
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(Runnable runnable) {
        create(null, runnable, null, 0);
    }

    /**
     * Constructs a new {@code Thread} with a {@code Runnable} object and name
     * provided. The new {@code Thread} will belong to the same {@code
     * ThreadGroup} as the {@code Thread} calling this constructor.
     *
     * @param runnable
     *            a {@code Runnable} whose method run will be
     *            executed by the new {@code Thread}
     * @param threadName
     *            the name for the {@code Thread} being created
     *
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(Runnable runnable, String threadName) {
        if (threadName == null) {
            throw new NullPointerException("threadName == null");
        }

        create(null, runnable, threadName, 0);
    }

    /**
     * Constructs a new {@code Thread} with no {@code Runnable} object and the
     * name provided. The new {@code Thread} will belong to the same {@code
     * ThreadGroup} as the {@code Thread} calling this constructor.
     *
     * @param threadName
     *            the name for the {@code Thread} being created
     *
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     *
     */
    public Thread(String threadName) {
        if (threadName == null) {
            throw new NullPointerException("threadName == null");
        }

        create(null, null, threadName, 0);
    }

    /**
     * Constructs a new {@code Thread} with a {@code Runnable} object and a
     * newly generated name. The new {@code Thread} will belong to the {@code
     * ThreadGroup} passed as parameter.
     *
     * @param group
     *            {@code ThreadGroup} to which the new {@code Thread} will
     *            belong
     * @param runnable
     *            a {@code Runnable} whose method run will be
     *            executed by the new {@code Thread}
     * @throws IllegalThreadStateException
     *             if group.destroy() has already been done
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(ThreadGroup group, Runnable runnable) {
        create(group, runnable, null, 0);
    }

    /**
     * Constructs a new {@code Thread} with a {@code Runnable} object, the given
     * name and belonging to the {@code ThreadGroup} passed as parameter.
     *
     * @param group
     *            ThreadGroup to which the new {@code Thread} will belong
     * @param runnable
     *            a {@code Runnable} whose method run will be
     *            executed by the new {@code Thread}
     * @param threadName
     *            the name for the {@code Thread} being created
     * @throws IllegalThreadStateException
     *             if group.destroy() has already been done
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(ThreadGroup group, Runnable runnable, String threadName) {
        if (threadName == null) {
            throw new NullPointerException("threadName == null");
        }

        create(group, runnable, threadName, 0);
    }

    /**
     * Constructs a new {@code Thread} with no {@code Runnable} object, the
     * given name and belonging to the {@code ThreadGroup} passed as parameter.
     *
     * @param group
     *            {@code ThreadGroup} to which the new {@code Thread} will belong
     * @param threadName
     *            the name for the {@code Thread} being created
     * @throws IllegalThreadStateException
     *             if group.destroy() has already been done
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(ThreadGroup group, String threadName) {
        if (threadName == null) {
            throw new NullPointerException("threadName == null");
        }

        create(group, null, threadName, 0);
    }

    /**
     * Constructs a new {@code Thread} with a {@code Runnable} object, the given
     * name and belonging to the {@code ThreadGroup} passed as parameter.
     *
     * @param group
     *            {@code ThreadGroup} to which the new {@code Thread} will
     *            belong
     * @param runnable
     *            a {@code Runnable} whose method run will be
     *            executed by the new {@code Thread}
     * @param threadName
     *            the name for the {@code Thread} being created
     * @param stackSize
     *            a stack size for the new {@code Thread}. This has a highly
     *            platform-dependent interpretation. It may even be ignored
     *            completely.
     * @throws IllegalThreadStateException
     *             if group.destroy() has already been done
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
        if (threadName == null) {
            throw new NullPointerException("threadName == null");
        }
        create(group, runnable, threadName, stackSize);
    }

    /**
     * Package-scope method invoked by Dalvik VM to create "internal"
     * threads or attach threads created externally.
     *
     * Don't call Thread.currentThread(), since there may not be such
     * a thing (e.g. for Main).
     */
    Thread(ThreadGroup group, String name, int priority, boolean daemon) {
        synchronized (Thread.class) {
            id = ++Thread.count;
        }

        if (name == null) {
            this.name = "Thread-" + id;
        } else {
            this.name = name;
        }

        if (group == null) {
            throw new InternalError("group == null");
        }

        this.group = group;

        this.target = null;
        this.stackSize = 0;
        this.priority = priority;
        this.daemon = daemon;

        /* add ourselves to our ThreadGroup of choice */
        this.group.addThread(this);
    }

可以看出,create(group, runnable, threadName, stackSize)是关键方法。

  /**
     * Initializes a new, existing Thread object with a runnable object,
     * the given name and belonging to the ThreadGroup passed as parameter.
     * This is the method that the several public constructors delegate their
     * work to.
     *
     * @param group ThreadGroup to which the new Thread will belong
     * @param runnable a java.lang.Runnable whose method run will
     *        be executed by the new Thread
     * @param threadName Name for the Thread being created
     * @param stackSize Platform dependent stack size
     * @throws IllegalThreadStateException if group.destroy() has
     *         already been done
     * @see java.lang.ThreadGroup
     * @see java.lang.Runnable
     */
    private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
        Thread currentThread = Thread.currentThread();
        if (group == null) {
            group = currentThread.getThreadGroup();//当前线程的线程组
        }

        if (group.isDestroyed()) {
            throw new IllegalThreadStateException("Group already destroyed");
        }

        this.group = group;

        synchronized (Thread.class) {
            id = ++Thread.count;
        }

        if (threadName == null) {
            this.name = "Thread-" + id;
        } else {
            this.name = threadName;
        }

        this.target = runnable;
        this.stackSize = stackSize;

        this.priority = currentThread.getPriority();

        this.contextClassLoader = currentThread.contextClassLoader;

        // Transfer over InheritableThreadLocals.
        if (currentThread.inheritableValues != null) {
            inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
        }

        // add ourselves to our ThreadGroup of choice
        this.group.addThread(this);
    }

可以看出,Thread构造函数中ThreadGroup为null,或者不包含ThreaGroup参数时,Thread都会被加入到当前线程的ThreadGroup中。

自定义ThreadPool

线程池可以理解为其中有多个固定的工作线程,然后不断从同一个任务队列中取得任务并执行。如果某线程取任务时没有任务,该线程处于wait()状态;当添加任务时,notiyfy()一次通知最近的处于wait()状态的线程。这符合一个生产者,多个消费者的模型。
这里参考《Java网络编程精解(孙卫琴)》P67的内容来编写自定义的ThreadPool。

public class ThreadPool extends ThreadGroup{
    private boolean isClosed=false;
    private LinkedList workQueue;//任务队列
    private static int threadPoolID;
    private int threadID;
    public ThreadPool(int poolSize) {
        // TODO Auto-generated constructor stub
        super("ThreadPool"+(threadPoolID++));
        setDaemon(true);
        workQueue=new LinkedList();
        for (int i = 0; i < poolSize; i++) {
            new WorkThread().start();//启用固定数量的线程
        }
    }
    public synchronized void execute(Runnable task){
        if (isClosed) {
            throw new IllegalStateException();
        }
        if (task!=null) {
            workQueue.add(task);
            notify();//唤醒一个wait()的线程
        }
    }
    /**
     * 通过interrupt()来通知线程组中所有的线程执行中断
     * */
    public synchronized void close(){
        if (!isClosed) {
            isClosed=true;
            workQueue.clear();
            interrupt();//中断所有线程
        }
    }
    public void join(){
        synchronized (this) {
            isClosed=true;//任务取得为null
            notifyAll();//唤醒所有线程
        }
        Thread[] threads=new Thread[activeCount()];
        int count=enumerate(threads);
        for (int i = 0; i < count; i++) {
            try {
                threads[i].join();//
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    protected synchronized Runnable getTask() throws InterruptedException{
        while (workQueue.size()==0) {
            if (isClosed) return null;
            wait();

        }
        return workQueue.removeFirst();
    }
    private class WorkThread extends Thread{
        public WorkThread() {
            // TODO Auto-generated constructor stub
            super(ThreadPool.this,"WokrThread-"+(threadID++));
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            while (!isInterrupted()) {
                Runnable task=null;
                try {
                    task=getTask();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (task==null) {
                    return;
                }
                task.run();

            }
        }

    }
}

这里进行测试。

public class Main {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ThreadPool pool=new ThreadPool(3);
        for (int i = 0; i < 10; i++) {
            pool.execute(createTask(i));
        }
        pool.join();//执行完正在执行的任务再结束
//      pool.close();//立即结束

    }
    private static Runnable createTask(final int taskID){
        return new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("Task"+taskID+":start");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    System.out.println("Task"+taskID+":end");
                }
            }
        };
    }

}

Java JDK线程池

Java线程池类

Java线程池原理与实例详解_第3张图片
真正实现的线程池类有3个。
(1) ThreadPoolExecutor
采用几个线程来执行提交的任务。其中一个构造函数如下:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) 

API参数如下:
corePoolSize :the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
maximumPoolSize :the maximum number of threads to allow in the pool
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.
unit the time:unit for the keepAliveTime argument
workQueue :the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
最常用的场景是通过Executors类的工厂方法来构造,包括newCachedThreadPool()、newFixedThreadPool(int) 、newSingleThreadExecutor() ,具体查看下一节。
(2) ScheduledThreadPoolExecutor
任务可以在一定时间后执行,也可以设置周期性执行。构造函数比较简单,只需要指定线程数量。主要方法在schedule相关的成员方法。例如:

public ScheduledFuture  scheduleWithFixedDelay (Runnable command, long initialDelay, long delay, TimeUnit unit)

API参数如下:
command:the task to execute
initialDelay :the time to delay first execution
delay :the delay between the termination of one execution and the commencement of the next
unit the time:unit of the initialDelay and delay parameters
返回值:
a ScheduledFuture representing pending completion of the task, and whose get() method will throw an exception upon cancellation
最常用的场景是通过Executors类的工厂方法来构造,包括newCachedThreadPool()、newFixedThreadPool(int) 、newSingleThreadExecutor() ,具体查看下一节。
(3) ForkJoinPool
Fork/Join模式的线程池,用于支持并行计算。更多的信息来源于JDK 7 中的 Fork/Join 模式。

Executors工厂方法初始化线程池

一般来讲,不直接初始化线程池对象。Executors中几个静态方法提供了线程池的实例化方法。
(1)只有一个工作线程的线程池(ThreadPoolExecutor)

/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
}
/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue, and uses the provided ThreadFactory to
     * create a new thread when needed. Unlike the otherwise
     * equivalent {@code newFixedThreadPool(1, threadFactory)} the
     * returned executor is guaranteed not to be reconfigurable to use
     * additional threads.
     *
     * @param threadFactory the factory to use when creating new
     * threads
     *
     * @return the newly created single-threaded Executor
     * @throws NullPointerException if threadFactory is null
     */
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue(),
                                    threadFactory));
    }

(2)固定线程数量(ThreadPoolExecutor)

/**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
}

    /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue, using the provided
     * ThreadFactory to create new threads when needed.  At any point,
     * at most {@code nThreads} threads will be active processing
     * tasks.  If additional tasks are submitted when all threads are
     * active, they will wait in the queue until a thread is
     * available.  If any thread terminates due to a failure during
     * execution prior to shutdown, a new one will take its place if
     * needed to execute subsequent tasks.  The threads in the pool will
     * exist until it is explicitly {@link ExecutorService#shutdown
     * shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue(),
                                      threadFactory);
    }

(3) 不固定数量的线程池(ThreadPoolExecutor)
如果线程不被使用,线程的存活时间为60s。

/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
}
  /**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available, and uses the provided
     * ThreadFactory to create new threads when needed.
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     */
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue(),
                                      threadFactory);
    }

(4)Fork/Join模式的线程池(ForkJoinPool)

  /**
     * Creates a thread pool that maintains enough threads to support
     * the given parallelism level, and may use multiple queues to
     * reduce contention. The parallelism level corresponds to the
     * maximum number of threads actively engaged in, or available to
     * engage in, task processing. The actual number of threads may
     * grow and shrink dynamically. A work-stealing pool makes no
     * guarantees about the order in which submitted tasks are
     * executed.
     *
     * @param parallelism the targeted parallelism level
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code parallelism <= 0}
     * @since 1.8
     * @hide
     */
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
}
/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @since 1.8
     * @hide
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

(5)单个线程的Scheduled类型线程池(ScheduledThreadPoolExecutor)

/**
     * Creates a single-threaded executor that can schedule commands
     * to run after a given delay, or to execute periodically.
     * (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newScheduledThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     * @return the newly created scheduled executor
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
}
/**
     * Creates a single-threaded executor that can schedule commands
     * to run after a given delay, or to execute periodically.  (Note
     * however that if this single thread terminates due to a failure
     * during execution prior to shutdown, a new one will take its
     * place if needed to execute subsequent tasks.)  Tasks are
     * guaranteed to execute sequentially, and no more than one task
     * will be active at any given time. Unlike the otherwise
     * equivalent {@code newScheduledThreadPool(1, threadFactory)}
     * the returned executor is guaranteed not to be reconfigurable to
     * use additional threads.
     * @param threadFactory the factory to use when creating new
     * threads
     * @return a newly created scheduled executor
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1, threadFactory));
    }

(6)多个线程的Scheduled类型线程池(ScheduledThreadPoolExecutor)

  /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @param threadFactory the factory to use when the executor
     * creates a new thread
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

实例-1:Network Service

这里写了一个线程池的网络服务器。

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 * created by CaoYanfeng
 * 一个简单的服务器程序。采用线程池来并发处理Socket。
 * */
public class NetworkService {
    private final ServerSocket serverSocket;
    private final ExecutorService pool;
    public NetworkService(int port,int poolSize) throws IOException {
        // TODO Auto-generated constructor stub
        serverSocket=new ServerSocket(port);
        pool=Executors.newCachedThreadPool();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            final NetworkService service=new NetworkService(8000, 3);
            service.run();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }




    }
    //关闭线程池
    public void shutdownAndAwaitTermination(ExecutorService pool){
        pool.shutdown();
        pool.shutdownNow();
        try {
            if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
                       System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
    public void run(){
        System.out.println("启动Service!");
        while (true) {
            try {
                pool.execute(new Handler(serverSocket.accept()));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                pool.shutdown();
                e.printStackTrace();

            }

        }

    }
    //socket处理的句柄
    private class Handler implements Runnable{
        private static final int BUFFER_SIZE=1024;
        private final Socket socket;
        private BufferedInputStream inputStream;
        public Handler(Socket socket) {
            // TODO Auto-generated constructor stub
            this.socket=socket;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
        try {
            inputStream=new BufferedInputStream(socket.getInputStream());
            byte[] buffer=new byte[BUFFER_SIZE];
            int validSize=0;
            while (socket.isConnected()&&(validSize=inputStream.read(buffer))!=0) {
                System.out.print(socket.getInetAddress()+":"+socket.getPort()+"---");
                for (int i = 0; i < validSize; i++) {
                    System.out.print(buffer[i]+" ");
                }
                System.out.println();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                socket.close();
                inputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        }

    }

}

实例-2:单任务执行结束后回调

有时候将耗时任务委托给线程池后,当执行结束,需要获得任务执行后的结果,或者单纯判断执行完毕。这里有一个实例,采用的是Runable子类FutureTask来封装任务。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
/**
 * created by 曹艳丰
 * 2016-08-05
 *采用FutureTask来返回线程执行完毕后的状态。
 *这里是一个任务
 * */
public class FutureTaskTest {

    public static  void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService service=Executors.newCachedThreadPool();
        FutureTask futureTask=new FutureTask(new Callable() {

            @Override
            public String call() throws Exception {
                // TODO Auto-generated method stub
                Thread.sleep(5000);
                return "耗时操作-0结束!";
            }
        });
        service.execute(futureTask);
        try {
            System.out.println(futureTask.get());//get()是一个阻塞函数
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        shutdownAndAwaitTermination(service);

    }
    //关闭线程池
    public static void shutdownAndAwaitTermination(ExecutorService pool){
        pool.shutdown();
        pool.shutdownNow();
        try {
            if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
                       System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

实例-3:多任务执行结束后回调

如果是多任务的话,ExecutorService有几个函数可以用来使用。
Java线程池原理与实例详解_第4张图片
这里我写了一个例子。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;
/**
 *  created by CaoYanfeng
 *  2016-08-05
 *采用FutureTask来返回线程执行完毕后的状态。
 *这里是多任务回调
 * */
public class MutileFutureTaskTest {

    public static  void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService service=Executors.newCachedThreadPool();

        Callable task1=new Callable() {

            @Override
            public String call() throws Exception {
                // TODO Auto-generated method stub
                Thread.sleep(2000);
                return "耗时操作-1结束!";
            }
        };
        Callable task2=new Callable() {

            @Override
            public String call() throws Exception {
                // TODO Auto-generated method stub
                Thread.sleep(2000);
                return "耗时操作-2结束!";
            }
        };
        Callable task3=new Callable() {

            @Override
            public String call() throws Exception {
                // TODO Auto-generated method stub
                Thread.sleep(2000);
                return "耗时操作-3结束!";
            }
        };

        List> tasks=new ArrayList>();
        tasks.add(task3);
        tasks.add(task2);
        tasks.add(task1);
        try {
            List> result=service.invokeAll(tasks);//阻塞函数,所有任务执行完毕后返回
            for (Future future : result) {
                try {
                    System.out.println(future.get());
                } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        shutdownAndAwaitTermination(service);

    }
    //关闭线程池
    public static void shutdownAndAwaitTermination(ExecutorService pool){
        pool.shutdown();
        pool.shutdownNow();
        try {
            if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
                       System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

}

你可能感兴趣的:(java)