Executors 工具类
下面主要是Executors支持的生成线程池的方式,主要有下面这些
executors生成一些常用的线程池方法 4·
(1)newSingleThreadExecutor
- 创建一个单线程的线程池。
- 这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。
- 如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。
- 此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
(2)newFixedThreadPool
- 创建固定大小的线程池。
- 每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
- 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
- 如果希望在服务器上使用线程池,建议使用 newFixedThreadPool方法来创建线程池,这样能获得更好的性能。
(3) newCachedThreadPool
- 创建一个可缓存的线程池。
- 如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60 秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
- 此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM)能够创建的最大线程大小。
(4)newScheduledThreadPool
- 创建一个大小无限的线程池。
- 此线程池支持定时以及周期性执行任务的需求。
Executor框架
Executor
- Java 5+中的 Executor 接口定义一个执行线程的工具。
- 它的子类型即线程池接口是 ExecutorService。
什么是 Executor 框架?为什么使用 Executor 框架?
- Executor 框架是一个根据一组执行策略调用,调度,执行和控制的异步任务的框架。
- 每次执行任务创建线程 new Thread()比较消耗性能,创建一个线程是比较耗时、耗资源的,而且无限制的创建线程会引起应用程序内存溢出。
- 所以创建一个线程池是个更好的的解决方案,因为可以限制线程的数量并且可以回收再利用这些线程。利用Executors 框架可以非常方便的创建一个线程池。
在 Java 中 Executor 和 Executors 的区别?
Executors 工具类的不同方法按照我们的需求创建了不同的线程池,来满足业务的需求。 Excutors:使用 ThreadPoolExecutor 可以创建自定义线程池。
Executor 接口对象能执行我们的线程任务。 Executor :ExecutorService 接口继承了 Executor 接口并进行了扩展,提供了更多的方法我们能获得任务执行的状态并且可以获取任务的返回值。
Future 表示异步计算的结果,他提供了检查计算是否完成的方法,以等待计算的完成,并可以使用 get()方法获取计算的结果。
public interface Executor {
void execute(Runnable command);
}
线程池中 submit() 和 execute() 方法有什么区别?
接收参数:
- execute()只能执行 Runnable 类型的任务。
- submit()可以执行 Runnable 和 Callable 类型的任务。
返回值:
- submit()方法可以返回持有计算结果的 Future 对象,
- 而execute()没有
异常处理:submit()方便Exception处理
execute案例
package threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecuteTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行线程");
}
});
}
}
}
执行结果:
pool-1-thread-1执行线程
pool-1-thread-2执行线程
pool-1-thread-1执行线程
这里可以发现,线程只有2个,而不是生成3个,是因为使用Executors.newFixedThreadPool 定义线程数量为2
submit案例
package threadPool;
import java.util.concurrent.*;
public class SubmitTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行runnable线程");
}
});
MyCallable myCallable = new MyCallable();
Future<Integer> future = executorService.submit(myCallable);
System.out.println("Callable返回结果"+future.get());
}
}
class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"执行callable");
return 2;
}
}
执行结果
pool-1-thread-1执行runnable线程
pool-1-thread-2执行callable
Callable返回结果2
可以发现,使用submit有以下的不同
- 可以抛出异常
- 可以获取Future获取返回结果
- 可以使用Runnable或者Callable
源码解析
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
ThreadPoolExecutor
底层还是使用了ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), 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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
主要参数有以下:
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
|