Java基本线程机制(二)

来源:互联网 发布:存储网络架构培训 编辑:程序博客网 时间:2024/05/21 16:25

三、Executor

Java SE 5以后,提供了Executor来管理Thread对象。Executor在客户端和任务执行之间提供了一个间接层,与Thread直接执行任务不同,这个中介对象将执行任务。有了Executor就不需要显示的管理线程的生命周期。

ExecutorService(具有服务周期的Executor)能够构建其阿丹的上下文来执行Runnable对象中的任务。

通常通过Executors的三个静态工厂方法来创建ExecutorService对象。

1、newCachedThreadPool();

 /**     * 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 <tt>execute</tt> 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.     *
     * 创建一个线程池,当需要新创建一个线程时,线程池就会创建新的线程。
     * 如果先前创建的线程可用(空闲),则线程池会复用先前的线程,此时不需要
     * 创建新的线程。这种线程池典型的适合于一个拥有许多的短生命周期线程的程序。
     * 如果没有可用的线程,则线程池会创建一个新的线程并加入线程池,如果线程
     * 空闲时间超过60秒,则该线程会被终止,并被移除线程池,释放资源。     * @return the newly created thread pool     */    public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>());    }

此线程池只会在需要线程去执行任务时才会去创建或复用线程。

用Executor执行任务。

public class CacheThreadPool {public static void main(String[] args) {ExecutorService exe = Executors.newCachedThreadPool();for(int i = 0; i < 5; i++){exe.execute(new LiftOff());}exe.shutdown();}}
shutdown()方法:防止新任务提交给这个Executor,即这个Executor不接受新的任务,之后再执行Executor.execute(Runnable run)方法不能执行任务,但是,在shutdown之前提交的任务还是会执行,当所有任务的执行完毕时,程序将会尽快退出。
2、newFixedThreadPool()

/**     * Creates a thread pool that reuses a fixed number of threads     * operating off a shared unbounded queue.  At any point, at most     * <tt>nThreads</tt> 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}.     *
     * 创建包含有固定线程数(nThread)的线程池,并且维护一个共享的等待队列。
     * 如果一个新加入的任务在提交时,所有的线程都是活动的,那么这个任务将被加入到
     * 一个等待队列,直到有线程空闲为止。如果一个线程因为在执行时期因为错误而被关掉并终止,
     * 此时,如果等待队列中还有未执行的任务,则线程池会创建一个新的线程来代替原来关闭的线程。
     * 线程池里的线程会一直存在,除非被明确的关闭。
     * @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<Runnable>());    }


线程池会在自身创建的时候,就一次性的创建所有的线程,同时可以限制创建的线程的数量,因为线程在一开始就被创建,而不是需要时才创建,所以以后用到线程时不需要创建线程,可以节省时间。

public class FixedThreadPool {public static void main(String[] args) {ExecutorService exe = Executors.newFixedThreadPool(5);for(int i = 0; i < 5; i++){exe.execute(new LiftOff());}exe.shutdown();}}

3、newSingleThreadPool()

/**     * 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     * <tt>newFixedThreadPool(1)</tt> 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<Runnable>()));    }

此线程池就是线程数为1的FixedThreadPool.如果给这个SingleThreadPool提交了多个任务,则这些任务将按提交时间顺序排队,一个一个的执行。

一个任务执行,只有当他前面的任务执行完毕之后才能开始。即会序列化提交给他的任务,并维护自己的悬挂任务队列。

如果有多个任务需要处理同一个资源,且多个任务不能同时更改资源,可以用此线程池来处理,从而可以避免在共享资源上做同步处理。

public class SingleThreadExecutor {public static void main(String[] args) {ExecutorService exe = Executors.newSingleThreadExecutor();for(int i = 0; i < 5; i++){exe.execute(new LiftOff());}exe.shutdown();System.out.println("I LOVE YOU");}}

从源码中可以看出,其实这三个方法返回的都是同一类对象,只是这三个方法在创建这类对象时的初始化参数不一样而已。

创建对象的方法为::

new ThreadPoolExecutor(nThreads, nThreads,                                      0L, TimeUnit.MILLISECONDS,                                      new LinkedBlockingQueue<Runnable>());    }
这个构造器里的

第一个参数是:构造的线程池中的核心线程数,所谓的核心线程可以简单的理解为线程池中最少需要拥有的线程。

第二个参数是:构造的线程池中最大的线程数。即该线程池最多拥有的线程数,如果线程池中已拥有的线程数等于这个最大值,并且所有线程都是活动的,此时如果提交给该线程池任务,则该任务会被挂起,加入到悬挂任务队列。

第三个参数是:一个long值,表示超时的数值。

第四个参数是:超时的时间单位。第三个和第四个一起,即线程空闲多久时间单位后,该线程会被终止。

第五个参数是:等待处理的任务队列,即悬挂任务队列。

ThreadPoolExecutor类中包含有线程池的一些统计信息方法,如最大线程数,核心线程数等,也包含一些线程的管理方法。

所有的上述三个方法都有一个重载的指定ThreadFactory的方法,这些重载方法的作用是用指定的线程工厂生成加入线程池的线程。

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {        return new ThreadPoolExecutor(nThreads, nThreads,                                      0L, TimeUnit.MILLISECONDS,                                      new LinkedBlockingQueue<Runnable>(),                                      threadFactory);    }
 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {        return new FinalizableDelegatedExecutorService            (new ThreadPoolExecutor(1, 1,                                    0L, TimeUnit.MILLISECONDS,                                    new LinkedBlockingQueue<Runnable>(),                                    threadFactory));    }

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>(),                                      threadFactory);    }


0 0
原创粉丝点击