Java基本线程机制(二)

三、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);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值