文档章节

java高并发设计(六)--jdk自身线程池特点

wangshuaixin
 wangshuaixin
发布于 2017/01/09 10:35
字数 1052
阅读 35
收藏 1

关于线程池的实现,jdk本身已经提供了四种线程池的实现,根据前面讲到的内容,我们这里可以整合前面的内容真正的理jdk线程池及相关的使用。

jdk自身线程池的实现主要有如下四种,主要是通过Executors工程来创建:

    1,newCachedThreadPool,可理解为无边界线程池,如果有任务提交过来,线程池中没有空余则直接创建线程来执行任务。

    2,newFixedThreadPool,指定容量的线程池,如果提交新任务过来,线程池没有达到指定容量且没有空余则创建新线程并执行任务,如果线程池已经达到指定容量则进入队列等待状态。

    3,newSingleThreadExecutor,单线程的线程池,该线程重复使用,保证提交到该线程池的任务按照先进先出等队列进行执行。

    4,newScheduledThreadPool,任务调度线程池,创建一个定长的线程池,保证任务的定期及周期性执行。

下面将分别讲解上面jdk提供的线程池的实现,将各个线程池的实现时我们先看下线程池创建的主工厂方法的源码:

public class Executors {

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

  
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

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

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

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

    /** Cannot instantiate. */
    private Executors() {}
}

只是提取了部分源码,可以看出每个线程池的实现都不是很复杂,并且内容已经实现了很多功能及组件。那下面我们将分别介绍四种不同的线程池:

一,ExecutorService service = Executors.newCachedThreadPool();无边界线程池,源码中是这样提现

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

可以看出无边界的最大值是Integer.MAX_VALUE,线程池等待队列是SynchronousQueue容量为1的队列,提交过来的任务会直接运行或者阻塞等待。

List<Future<String>> list = new ArrayList<Future<String>>();
		ExecutorService service = Executors.newCachedThreadPool();
		for(int i = 0; i < 10; i++) {
			final int index = i;
			service.execute(new Runnable() {
				@Override
				public void run() {
					System.out.println("execute pool" + index);
				}
			});
			
			Future<String> future = service.submit(new Callable<String>() {

				@Override
				public String call() throws Exception {
					// TODO Auto-generated method stub
					return "submit pool" + index;
				}
			});
			list.add(future);
		}
		
		for (Future<String> future : list) {
			System.out.println(future.get());
		}
		
		
		service.shutdown();

二,ExecutorService service = Executors.newFixedThreadPool(10);源码上可以体现,使用的最小,最大线程数量都是初始化的数值,并且使用的阻塞队列是LinkedBlockingQueue,链表的阻塞队列。

List<Future<String>> list = new ArrayList<Future<String>>();
		ExecutorService service = Executors.newFixedThreadPool(10);
		for(int i = 0; i < 10; i++) {
			final int index = i;
			service.execute(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("execute pool" + index);
				}
			});
			
			Future<String> future = service.submit(new Callable<String>() {

				@Override
				public String call() throws Exception {
					// TODO Auto-generated method stub
					return "submit pool" + index;
				}
			});
			list.add(future);
		}
		
		for (Future<String> future : list) {
			System.out.println(future.get());
		}
		
		
		service.shutdown();

从代码的运行就可以看出来,后面的10个线程执行会有一个线程等待的时间。

三,ExecutorService serviceSingle = Executors.newSingleThreadExecutor();从源码上可以体现该线程池的最小,最大都是1,并且使用的是LinkedBlockingQueue的链表阻塞队列,每次只能有一个线程任务在执行。

ExecutorService serviceSingle = Executors.newSingleThreadExecutor();
		for(int i = 0; i < 10; i++) {
			final int index = i;
			serviceSingle.execute(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("execute pool" + index);
				}
			});
		}
		
		serviceSingle.shutdown();

从代码运行结果上可以很明显的看出。

四,ScheduledExecutorService service = Executors.newScheduledThreadPool(1);从源码上可以看出,初始大小是指定的大小,最大值是Integer.MAX_VALUE,并且使用的阻塞队列是DelayedWorkQueue。

ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
		for(int i = 0; i < 10; i++) {
			final int index = i;
			service.schedule(new Runnable() {
				
				@Override
				public void run() {
					System.out.println("Scheduled pool" + index);
					
				}
			}, 5, TimeUnit.SECONDS);
			
		}
		
		service.shutdown();

从代码的运行结果上可以看出任务调度线程池的特点

© 著作权归作者所有

wangshuaixin

wangshuaixin

粉丝 19
博文 51
码字总数 60654
作品 1
海淀
架构师
私信 提问
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
8
进一步理解Java中的线程(下)

要想真正的理解Java并发编程,线程是无论如何都必须要彻底理解的一个重要概念。那么,在开始深入介绍之前,我们先来深入的学习一下线程。前面一个章节中已经介绍过线程的一些基本知识,包括线...

HollisChuang's Blog
2018/12/22
0
0
Java并发编程面试必备的知识点!

相信不用我说,大家也都知道掌握并发编程对于一个 Java 程序员的重要性。但相对于其他 Java 基础知识点来说,并发编程更加抽象,涉及到的知识点很多很零散,实际使用也更加麻烦。以至于很多人...

架构师技术联盟
03/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spark Streaming的优化之路——从Receiver到Direct模式

          作者:个推数据研发工程师 学长 1 业务背景 随着大数据的快速发展,业务场景越来越复杂,离线式的批处理框架MapReduce已经不能满足业务,大量的场景需要实时的数据处理结果来...

个推
45分钟前
2
0
壮丽70年·奋斗新时代|蒸妙集团熏蒸中会阴熏蒸的神奇好处

聚结相合之处为会。会阴居两阴间,为督、任、冲三脉的起点,三脉背出两阴之间,会聚阴部,因名会阴。会阴,经穴名。出《针灸甲乙经》。会阴别名屏翳、下极、金门。属任脉。在会阴部,男性当阴...

公益传承
54分钟前
2
0
pentaho-kettle-8.2.0.0-R源码开发环境搭建

1.从Kettle官网下载源码,本文使用的是pentaho-kettle-8.2.0.0-R 下载地址:https://codeload.github.com/pentaho/pentaho-kettle/zip/8.2.0.0-R 2.打开eclipse,选择一个新的工作空间,然后设...

gq_2010
今天
1
0
lua web快速开发指南(7) - 高效的接口调用 - httpc库

httpc库基于cf框架都内部实现的socket编写的http client库. httpc库内置SSL支持, 在不使用代理的情况下就可以请求第三方接口. httpc支持header、args、body、timeout请求设置, 完美支持各种h...

水果糖的小铺子
今天
5
0
通过四道常问面试题,带你了解什么是数据库分库分表

编者语:为了避免被误解为:「手里有把锤子,看什么都是钉子!」,说明一下不是什么业务都适合分布式数据库,更不是用了分布式数据库性能就一定能得到扩展。 其次:本文为纯干货,建议先转发...

老道士
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部