java 线程池使用及原理

一、线程池原理


线程池真正的实现为 ThreadPoolExecutor

构造方法:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
参数说明:

1. corePoolSize :核心线程数,默认情况下,核心线程会一直存活。

如果将 线程池对象的allowCoreThreadTimeOut 设置为true,则核心线程也会有超时策略。超时时间由 keepAliveTime 指定

2. maximumPoolSize:最大线程数,当活动线程数到达这个数值后,新的任务将被阻塞

3. keepAliveTime:非核心线程闲置时超时时长,非核心线程闲置超过此时长,将被回收。

当allowCoreThreadTimeOut为true时,核心线程闲置超过此时长也会被回收。

4. unit:keepAliveTime的单位,常用:TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒),TimeUnit.MINUTES(分钟)。

5.workQueue:线程池中的任务队列,通过execute提交的 Runnerable参数都会储存在此队列中。

6.threadFactory:线程工厂,为线程池提供新建线程的功能

7. handler:线程池无法执行新任务时,(比如:任务队列已满)会调用handler 的 rejectedExecution方法通知调用者。(此参数不常用,默认AbortPolicy)。


ThreadPoolExecutor执行任务时规则:

1. 如果线程池中 线程数量未达到核心线程数量(corePoolSize),则直接启动一个核心线程执行任务。

2. 如果线程池中 线程数量已达到核心线程数量(corePoolSize),则任务会被插入到任务队列(workQueue)中等待执行。

3. 如果步骤2无法插入到任务队列(任务队列已满),此时如果线程数量未达到最大线程数(maximumPoolSize),那么会立刻启动一个非核心线程执行任务。

4. 步骤3中如果线程数量已达到最大线程数(maximumPoolSize),会调用 RejectedExecutionHandler 的 rejectedExecution 方法通知调用者。


二、线程池的使用及优点

优点:

    1.重用线程池中的线程,减少线程创建和销毁带来的性能开销

    2. 能有效控制线程池的最大并发数,避免线程之间因相互抢占资源造成的阻塞

    3. 能对线程进行简单管理,并提供定时执行 及 指定间隔循环执行等功能


四种线程池的特点及简单的使用

1.缓存线程池 CachedThreadPool

线程数量不定,当线程池中线程都处于活动状态时,会创建新线程处理新任务,

否则会利用空闲线程处理新任务。

线程池中的线程都有超时机制,超时时长为60秒。(即超过60秒未处理任务的线程会被回收)

	public static void main(String[] args) {
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			try {
				Thread.sleep(index * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//以一个子线程执行打印方法
			//第一次执行时新建一个子线程
			//第二次及以后执行时,由于第一个线程已空闲,因此会复用第一个线程,不会新建
			cachedThreadPool.execute(new Runnable() {
				public void run() {
					System.out.println(index);
				}
			});
		}
	}

CachedThreadPool实际为只有非核心线程,超时时长为60秒的ThreadPoolExecutor。

SynchronousQueue很多情况下可理解为不可存储元素的队列。

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


2.定长线程池 FixedThreadPool

线程数量固定,线程处于空闲状态时,不会被回收,除非线程池关闭。

当所有线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。

public static void main(String[] args) {
	ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);//线程池固定长度为3
	for (int i = 0; i < 10; i++) {
		final int index = i;
		fixedThreadPool.execute(new Runnable() {
			public void run() {
				try {
					System.out.println(index);
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
	}
}

结果:每次打印3个数字,两秒后再打印三个,两秒后再打印3个(每次的三个数字顺序不保证)

FixedThreadPool实际为只有核心线程,超时时长0秒,任务队列大小没有限制的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<Runnable>());
    }



3.ScheduledThreadPool

核心线程数固定,非核心线程数没有限制。

非核心线程闲置时会被立即回收

一般用于定时执行任务,和执行具有固定周期的重复任务

(1)  定时执行任务(只执行一次)

	public static void main(String[] args) {
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
		scheduledThreadPool.schedule(new Runnable() {
			public void run() {
				System.out.println("delay 3 seconds");
			}
		}, 1, TimeUnit.SECONDS);	//只执行一次,注意和重复执行的参数个数不同
	}
结果:程序运行三秒后,打印出  delay 3 seconds

(2) 定期执行任务(重复执行)

public static void main(String[] args) {
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
		scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
			public void run() {
				System.out.println("delay 1 seconds, and excute every 3 seconds");
			}
		}, 1, 3, TimeUnit.SECONDS);	//延迟1秒后每3秒执行一次
	}

运行结果:运行一秒后,打印 delay 1 seconds, and excute every 3 seconds ,然后每3秒打印一次  delay 1 seconds, and excute every 3 seconds

ScheduledThreadPool实际为一个 核心线程数固定,最大线程数没有限制, 超时时长为0ms,的ThreadPoolExecutor

    /**
     * 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 new {@code ScheduledThreadPoolExecutor} with the
     * given core pool size.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }


4.  单线程化的线程池  SingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务都在同一个线程中按顺序执行

优点:统一所有外界任务到一个线程中,使这些任务之间不需要处理线程同步的问题。

	public static void main(String[] args) {
		ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			singleThreadExecutor.execute(new Runnable() {
				public void run() {
					try {
						System.out.println(index);
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
		}
	}

运行结果: 依次打印出  0到9  ,每2秒打印一个

单线程线程池实际为一个 核心线程数为1,最大线程数为1,超时时长为0ms,的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<Runnable>()));
    }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值