Java线程池
来源:互联网 发布:城市天际线mod软件 编辑:程序博客网 时间:2024/06/10 02:52
Java的线程池存在于java.util.concurrent包中的Executor框架。Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。他们的关系为
图片来自第七城市网。
public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion of the {@code Executor} implementation. * * @param command the runnable task * @throws RejectedExecutionException if this task cannot be * accepted for execution * @throws NullPointerException if command is null */ void execute(Runnable command);}
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <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;}
Excutors为真正的实现者。Executor作为顶级接口,ExecutorService接口继承了Executor接口,也是线程池ThreadExecutorPool线程池实现的接口。
建造线程池的方法有五种,分别建造不同的线程池:
newCachedThreadPool
newFixedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
newSingleThreadScheduledExecutor
五种方法都会建造一个线程池,我们取其中一个解读一下:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
可见,调用该方法最终返回了一个新建的ThreadPoolExecutor类型对象,也就是我们说的线程池。
继续追踪:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
ThreadPoolExecutor的构造函数,第一个参数是corePoolSize,核心线程数,核心线程在线程池中永远活跃。第二个参数maximunPoolSize,最大线程数,线程池可以运行的最大的线程数量。第三个参数keepAliveTime,非核心线程保持存活的时间。第四个参数unit,时间的单位。第五个参数workQueue,阻塞队列。
线程池中的核心线程始终保持活跃,当有任务来时,如果有核心线程空闲,立刻让其执行任务;如果没有核心线程空闲,即将任务加入工作队列。如果工作队列已满,又有任务过来了,那么开启一个新线程,执行任务,此时工作队列一直保持满的状态。开启的非核心线程执行任务结束后,如果在存活时间内没有接到任务,就会被关闭。当开启的线程数目达到最大线程数目,阻塞队列也已经排满,将会调用第七个参数defaultHandler,实行拒绝策略。
可见,上文的构造函数实际上调用了另一构造函数完成了构造。下面来看一看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; }
由上可见,原生构造函数实际上有七个参数,除了上面提到的五个,还有ThreadFactory类型参数和RejectedExecutionHandler类型参数。第七个参数RejectedExecutionHandler上文也提到过了,它是线程池在线程达到最大线程数,且阻塞队列也达到满的状态时,调用的拒绝策略。
RejectedExecutionHandler:
public interface RejectedExecutionHandler { /** * Method that may be invoked by a {@link ThreadPoolExecutor} when * {@link ThreadPoolExecutor#execute execute} cannot accept a * task. This may occur when no more threads or queue slots are * available because their bounds would be exceeded, or upon * shutdown of the Executor. * * <p>In the absence of other alternatives, the method may throw * an unchecked {@link RejectedExecutionException}, which will be * propagated to the caller of {@code execute}. * * @param r the runnable task requested to be executed * @param executor the executor attempting to execute this task * @throws RejectedExecutionException if there is no remedy */ void rejectedExecution(Runnable r, ThreadPoolExecutor executor);}
ThreadFactory:
public interface ThreadFactory { /** * Constructs a new {@code Thread}. Implementations may also initialize * priority, name, daemon status, {@code ThreadGroup}, etc. * * @param r a runnable to be executed by new thread instance * @return constructed thread, or {@code null} if the request to * create a thread is rejected */ Thread newThread(Runnable r);}
很明显,它是用来创建线程的。
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }这是newCachedThreadPool函数另一个重载形式。我们也可以调用这种构造函数指定ThreadFactory,设置线程池中的线程属性。
线程提交到线程池,需要调用ExecutorService接口中的submit函数:
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);
线程池的submit函数有三种重载形式。三种形式的函数的返回值也不完全相同。
第一种,参数为Callable<T>类型,返回值为<T> Future<T>类型,均为可变参数。
第二种,参数为Runnable类型和T类型,返回值为<T> Future<T>类型。
第三种,参数为Runnable类型,返回值为Future<?>类型。
@FunctionalInterfacepublic interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception;}Callable和Runnable类似,Callable<T>接口中仅有一个call方法,Runnable接口中仅有一个run方法,它们都是开启的新线程运行的函数体。不过Callable<T>的cal方法是有返回值的,返回值的类型也为T。
返回值的类型为Future<T>:
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;}Future<T>中有多种方法,给使用者用来控制提交的任务的运行。cancel方法用来取消任务,参数用来确定是否允许在线程运行时进行中断。isCancelled方法用来查看任务是否被取消。isDone方法用来查看任务是否已经完成。get方法接收任务运行结束后的返回结果,这是一个阻塞操作。第二个get方法设置了阻塞的时长和时间单位。
由于Runnable的run方法没有返回值,所以,在submit中把Runnable作为参数还想要返回值的话,需要自己设定一个T类型的result参数,任务运行结束后,将返回result的值作为结果。
我们使用Executors创建的线程池,其最大线程都为Integer.MAX_VALUE,所以为了安全起见,我们一般直接使用ThreadPoolExecutor来创建线程池。
- Java线程:线程池
- java--线程--线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(五):线程池
- Java线程_07_线程池
- Java线程(五):线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(六):线程池
- 线程安全和可重入函数
- C++静态类型、动态类型与多态性探讨
- JAVA水晶报表
- easyUI tabs 引用其他页面
- Unity3D研究院之挥动武器产生的剑痕特效(四十七)
- Java线程池
- 图论学习笔记
- Ubuntu网络设置
- Android 四大布局总结
- Python笔记:打印,变量类型,类型转换,运算符
- jsp基础知识点系列
- servlet流程和执行周期
- 419. Battleships in a Board
- Luban压缩源码学习