《Java并发编程实战》读书笔记——线程池、Callable、Future、FutureTask

1、Executor和ExecutorService

    基于生产者——消费者模式,提交任务的线程是生产者,执行的是消费者。

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

    为了解决执行服务的生命周期问题,有了ExecutorService接口,添加了一些用于生命周期管理的方法。线程池有RUNNING、SHUTDOWN(调用shutDown())、STOP(调用shutDownNow()),TERMINATED(销毁线程、清空队列)四种状态。

public interface ExecutorService extends Executor {

	// 平稳关闭,不再接受新任务,等待已提交的任务执行完成,包括那些还未开始执行的任务
	void shutdown();

	// 停止正在执行的任务,取消等待中的任务,返回等待执行的任务的List
	List<Runnable> shutdownNow();

	// 当调用shutdown()方法后返回为true。
	boolean isShutdown();

	// 当调用shutdown()方法后,并且所有提交的任务完成后返回为true
	boolean isTerminated();

	/**
	 * 调用此方法,在shutdown请求发起后,除非以下任何一种情况发生,否则当前线程将一直到阻塞。
	 * 1、所有任务执行完成
	 * 2、超过超时时间 
	 * 3、当前线程被中断
	 */
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
	
	// 提交一个带有返回值的任务(Callable),返回值为Future,表示了任务的执行完成结果,Future.get()方法返回成功执行后的结果。
	<T> Future<T> submit(Callable<T> task);
	
	// 提交一个Runnable任务执行,返回一个Future做为任务task的代理,Future.get()方法在执行成功后可以返回result。
	<T> Future<T> submit(Runnable task, T result);

	Future<?> submit(Runnable task);

	// 执行一组任务,返回一个Future的list,其中的Future持有任务执行完成的结果和状态 
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
			throws InterruptedException;
	
	// 执行一组任务,当成功执行完一个任务(没有抛异常),就返回结果,不论正常返回还是异常结束,未执行的任务都会被取消。
	<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;

	<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
			throws InterruptedException, ExecutionException, TimeoutException;
}


2、Executors

    返回ExecutorService的工厂类,返回不同的线程池,都利用了ThreadPoolExecutor类,ThreadPoolExecutor构造器有如下几个参数

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

    corePoolSize:核心池大小。创建线程池后,    线程池中没有线程,任务来了再创建线程,线程数达到corePoolSize后,任务放进阻塞队列workQueue;

    maximumPoolSize:最大线程数。只有当workQueue已满时,线程池才会创建新线程,直到线程数达到maximumPoolSize;

    keepAliveTime,unit:当线程数大于corePoolSize且线程的空闲时间大于keepAliveTime,销毁该线程,如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0;

    workQueue:存储等待执行任务的队列,当线程数量达到corePoolSize时,新到达的任务放入该阻塞队列,如果阻塞队列满了,则创建新的线程;

    threadFactory:线程工厂;

    handler:表示拒绝处理任务时的策略,当workQueue已满且线程数达到maximumPoolSize时调用。有【1】丢弃任务并抛出RejectedExecutionException异常(AbortPolicy,默认的)【2】丢弃任务,不抛出异常(DiscardPolicy)【3】丢弃任务队列最前面的任务,然后尝试重新提交新的任务(DiscardOldestPolicy,不适合与优先级队列一起使用)【4】由调用线程处理该任务(CallerRunsPolicy);等四种策略。

// 节选自jdk1.8
public class Executors {
	/**
	 * corePoolSize = maximumPoolSize =nThreads 
	 * 默认使用无界的LinkedBlockingQueue
	 * keepAliveTime为0,线程空闲即销毁(线程数大于corePoolSize且队列里无任务) 
	 * 未指定threadFactory和handler,则使用默认的,分别为Executors的内部类DefaultThreadFactory,AbortPolicy
	 */
	public static ExecutorService newFixedThreadPool(int nThreads) {
		return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<Runnable>());
	}
	
	// 创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不穿如并行级别参数,将默认为当前系统的CPU个数
	public static ExecutorService newWorkStealingPool(int parallelism) {
		return new ForkJoinPool(parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
	}

	// 和newFixedThreadPool一样,只是corePoolSize = maximumPoolSize = 1
	public static ExecutorService newSingleThreadExecutor() {
		return new FinalizableDelegatedExecutorService(
				new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
	}
	
	/** corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE
	 * 	keepAliveTime = 1 min
	 * 	要将元素放入SynchronousQueue中,必须有另一个线程在等待接受这个元素,否则创建新线程
	 * */
	public static ExecutorService newCachedThreadPool() {
		return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
	}
	
	// 创建一个定长线程池,支持定时及周期性任务执行,使用DelayQueue,只有元素逾期后,才能take(),元素根据逾期时间排序
	public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
		return new ScheduledThreadPoolExecutor(corePoolSize);
	}

	public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
		return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
	}
}


3、Callable、Future、FutureTask

    (1)Callable有返回值,可以抛出RuntimeException,Runnable无返回值,不可以抛出异常(没有返回值,没有其它线程处理异常)

    (2)Future表示任务的生命周期,ExecutorService中的submit()返回Future,任务未完成get()会阻塞,get()可以指定时间

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

    (3)FutureTask,可以执行多任务计算,可以在高并发环境下保证任务只执行一次。有等待运行、正在运行、运行完成三种状态,完成状态包括因取消或异常结束,完成后停止在这个状态上。

    完成后get()立即返回,否则阻塞。完成后返回结果或者抛出异常,FutureTask将计算结果从计算线程传递到get()的线程。

// 节选了jdk1.8的get()方法,RunnableFuture extends Runnable, Future
public class FutureTask<V> implements RunnableFuture<V> {
	
	// 各种状态值,以前用AQS实现,状态用AQS里的state表示
	private volatile int state;
	private static final int NEW = 0;
	private static final int COMPLETING = 1;
	private static final int NORMAL = 2;
	private static final int EXCEPTIONAL = 3;
	private static final int CANCELLED = 4;
	private static final int INTERRUPTING = 5;
	private static final int INTERRUPTED = 6;

	public V get() throws InterruptedException, ExecutionException {
		int s = state;
		if (s <= COMPLETING)
			s = awaitDone(false, 0L);
		return report(s);
	}

	private int awaitDone(boolean timed, long nanos) throws InterruptedException {
		final long deadline = timed ? System.nanoTime() + nanos : 0L;
		WaitNode q = null;
		boolean queued = false;
		for (;;) {
			if (Thread.interrupted()) {
				removeWaiter(q);
				throw new InterruptedException();
			}

			int s = state;
			// 完成返回
			if (s > COMPLETING) {
				if (q != null)
					q.thread = null;
				return s;
				// 未完成则让步
			} else if (s == COMPLETING)
				Thread.yield();
			else if (q == null)
				q = new WaitNode();
			else if (!queued)
				queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
			else if (timed) {
				nanos = deadline - System.nanoTime();
				if (nanos <= 0L) {
					removeWaiter(q);
					return state;
				}
				LockSupport.parkNanos(this, nanos);
			} else
				LockSupport.park(this);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值