线程不能重复启动,创建或销毁线程存在一定的开销,所以利用线程池技术来提高系统资源利用效率,并简化线程管理。
Executor 框架
Java提供的线程池框架主要涉及到如下的类和接口:
Executor 框架基本组成
下面是相应的代码:
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {… …}
public class ThreadPoolExecutor extends AbstractExecutorService {… …}
工具类 Executors
主要提供以下几种预配置的线程池:
1. newFixedThreadPool(int nThreads) 创建一个包含nThreads个线程的线程池,共享一个无边界的工作队列,在任何时刻,线程池最多有nThreads个存活线程;当某个线程由于执行过程中出现错误而死亡,则新建一个线程以补充。
Executor exe = Executors.newFixedThreadPool(5);
exe.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
2. newCachedThreadPool() 创建一个线程池,当新任务被提交,如果池中没有空余的存活线程,则该线程池会创建新的线程;如果有存活的多余的线程则会复用该线程;当某个线程空闲超过60秒的时候,该线程会被终止然后被移除线程池。
这种线程池适合被用于处理大量耗时短的任务,因为设置了一个空闲超时时间,这样当整个线程池都闲下来时,基本不会占用额外的资源。其内部使用 SynchronousQueue 作为工作队列。
Executor exe = Executors.newCachedThreadPool();
exe.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
});
3. newSingleThreadExecutor() 创建仅仅包含一个线程的线程池,维护着一个无边界的工作队列,在任何时刻,线程池只能有一个任务被执行,任务被保证顺序的执行。如果线程由于执行过程中出现错误而死亡,则新建一个线程代替继续执行任务;和newFixedThreadPool(1)不一样,一旦线程池创建,该线程池不能再进行配置。这是通过将ThreadPoolExecutor 包装类实现的,因此该方法返回的Executor不能强制转化为ThreadPoolExecutor;
4.
newSingleThreadScheduledExecutor() 和 newScheduledThreadPool(int coreThreadSize) 分别是创建包含一个线程和指定数量的线程,该线程池的线程定时的执行一些任务;
5. newWorkStealingPool(int parallelism),newWorkStealingPool是jdk1.8才有的,会根据所需的并行层次来动态创建和关闭线程,通过使用多个队列减少竞争,底层用的ForkJoinPool来实现的。
ForkJoinPool的优势在于,可以充分利用多cpu、多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。
有两个方法用于创建ForkJoin框架中用到的ForkJoinPool线程池,第一个函数中的参数用于指定并行数,第二个函数没有参数,它默认使用当前机器可用的CPU个数作为并行数。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!