在上一文中,主要介绍了创建线程池的方法,以及java提供的线程池管理线程的几个方法。在本文中我们主要介绍线程池执行任务。
上文中介绍四种创建线程池方法,但是返回的都是一个 接口ExecutorService,该接口继承自Executor。Executor中只定义了一个方法来执行任务,在
ExecutorService中,正如其名字的一样,定义了一个服务,定义了完整的线程池的行为,可以接受提交任务、执行任务、关闭服务。抽象类
AbstractExecutorService类实现了ExecutorService接口,也实现了接口定义的默认行为。 AbstractExecutorService
中任务提交的submit方法有三个实现。
第一个接收一个Runnable的Task,没有执行结果;submit(Runnable task)
第二个是两个参数:一个Runnable 任务,一个执行结果;submit(Runnable task, T result)
第三个一
个Callable,本身就包含执任务内容和执行结果。submit(Callable task)
这三种submit方法的返回结果都是Future类型,调用该接口定义的get方法即可获得执行结果。V get() 方法的返回值类型V是在提交任务时就约定好了的。
以第一种为例,其代码实现为:
public Future> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
利用newTaskFor()方法创建了一个实现Runnale接口的RunnableFuture 任务,然后调用Excutor的execute()方法执行该任务,然后又作为submit方法的返回值返回。代码虽然只有简单的几行,但是线程池什么时候创建新的作业线程来处理任务,什么时候只接收任务不创建作业线程,另外什么时候拒绝任务。想必大家都已经猜出线程池的接收任务、维护工作线程的策略都要在方法execute()方法中实现。
在方法execute(Runnable command)中调用到几个重要的方法: addIfUnderCorePoolSize,workQueue.offer(command) ,ensureQueuedTaskHandled(command),addIfUnderMaximumPoolSize(command)这几个操作。顾名思义,就可以知道该方法具体是什么意思。构建线程池时定义了一个额定大小的线程数,当线程池内工作线程数小于额定大小,有新任务进来就创建新工作线程,如果超过该阈值,则一般就不创建了,只是把接收任务加到任务队列里面。但是如果任务队列里的任务实在太多了,那还是要申请额外的工作线程来帮忙,就是需要扩大线程数。如果还是不够用就拒绝服务。
下面就介绍一下Runnable和Callable的区别:
相同点:两者都是接口;
public interface Callable {
V call() throws Exception;
}
public interface Runnable {
public abstract void run();
}
2. 两者都可用来编写多线程程序;
3.两者都需要调用Thread.start()启动线程;
不同点:两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
运行Callable任务可以拿到一个Future对象,Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如果线程没有执行完,Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常,Future.get()会throws
InterruptedException或者ExecutionException;如果线程已经取消,会跑出CancellationException。取消由cancel 方法来执行。isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明Future> 形式类型、并返回 null 作为底层任务的结果。
上面就是介绍的多线程下创建线程池,然后执行任务。只是介绍比较浅显的知识,如果需要更深的知道线程池的原理性知识,还需要自己查询API,我认为只有自己去亲手实验的东西才算自己的。
以上内容只代表个人观点,如有异议,恳请批评指正。