1、相关类

  Executors  ExecutorService   Callable   ThreadPool     Future

2、相关接口

  Executor

Executor接口的使用:

  

public class TestExecutor implements Executor{
@Override
public void execute(Runnable command){
//调用execute方法常常传入runnable接口对象,开启线程
} }

  ExecutorService接口的使用:(继承Executor接口)

/**
*submit方法(执行runnble、callable对象的线程)
*实现类:各种线程池
*/
Callable接口 && Runnable接口
callable调用call方法
runnable调用run方法
都可以被线程调用,但callable的call方法具有返回值(泛型)
Executors类(操作Executor的工具类)
ExecutorService service = Executors.newFixedThreadPool(5);//创建5个线程的线程池
ThreadPool线程池类(装着线程的容器)
线程池创建的固定线程,线程任务执行完后线程不会消失,处于等待任务的状态(idel)。
    线程任务大于线程池容量时,多出来的任务放在等待队列中(内部使用BlockingQueue实现)
public class TestThreadPool{
2
public static void main(String[] args){
3
ExecutorService service = Executors.newFixedThreadPool(5);//1.创建5个线程的线程池容器
4 5
for(int i=0;i<6;i++){//2.放6个任务,线程池一次只能放5个,所以第6个任务需要重复使用旧的线程
6
service.execute(() -> {
7
System.out.println(Thread.getCurrentThread().getName());//3.打印出当前线程名
8
});
9
}
10
service.shutdown();//执行完当前任务则关闭线程
11
service.shutdownNow();//无论是否执行完都关闭线程
12
}
13
}

  Future接口(线程未来产生的返回值)

public class TestFuture{
2
public static void main(String[] args){
3
//FutureTask实现类Runnable和Future接口
4
FutureTask<Integer> task = new FutureTask<>(
5
Thread.sleep(500);//阻塞等待500毫秒
6
return 1000;
7
);
8 9
//new的方式启动线程任务
10
new Thread(task).start();
11
System.out.println(task.get());//阻塞等待500毫秒后得到返回值
12
///////////////////////////////////////////////////////////////////
13
ExecutorService service = Executors.newFixedThreadPool(5);//创建5个线程的线程池
14
Future<Integer> future = service.submit(()->{//相当于运行类callable接口的call方法,返回1
15
Thread.sleep(500);
16
return 1;
17
});
18
System.out.println(future.get());//阻塞等待500毫秒后得到返回值
19
}
20
}

  WorkStealingPool偷任务线程池

  底层采用ForkJoinPool实现(开启的是Deamon守护线程,主线程退出则线程退出)

  

public class WorkStealingPoolTest {
2
public static void main(String[] args) throws IOException {
3
//根据CPU核数启动相应个数的线程(4核cpu---4个线程)
4
ExecutorService service = Executors.newWorkStealingPool();
5
System.out.println(Runtime.getRuntime().availableProcessors());
6
7
service.execute(new R(1000));//线程1执行任务1----1秒
8
service.execute(new R(2000));//线程2执行任务2----2秒
9
service.execute(new R(2000));//线程3执行任务3----2秒
10
service.execute(new R(2000));//线程4执行任务4----2秒
11
service.execute(new R(2000));//任务5阻塞,当线程1执行完后把任务5偷过来执行
12 13
//由于产生的是守护线程,主线程不阻塞的话,看不到输出
14
System.in.read();//将主线程阻塞
15
}
16
17
static class R implements Runnable {
18
19
int time;
20
21
R(int t) {
22
this.time = t;
23
}
24
25
@Override
26
public void run() {
27 28
try {
29
TimeUnit.MILLISECONDS.sleep(time);
30
} catch (InterruptedException e) {
31
e.printStackTrace();
32
}
33
//打印线程名---ForkJoinPool
34
System.out.println(time + " " + Thread.currentThread().getName());
35 36
}
37
38
}
39
}

  ForkJoinPool(分支合并线程池)

  思想:分治,把大任务拆分成小任务并行计算,计算完成后将结果合并

  守护线程

  

public class ForkJoinPoolTest{
2 3
public static void main(String[] args) throws Exception {
4
ForkJoinPool pool = new ForkJoinPool();
5
MyTask task = new MyTask(inits, 0, inits.;ength-1);
6
ForkJoinTask<int[]> taskResult = pool.submit(task);
7
try {
8
taskResult.get();//阻塞等待所有线程结果计算完成
9
} catch (InterruptedException | ExecutionException e) {
10
e.printStackTrace(System.out);
11
}
12
}
13
14
/**
15
* 单个排序的子任务
16
*/
17
static class MyTask extends RecursiveTask<int[]> {
18
19
private int[] source;
20
private int start;
21
private int end;
22
23
public MyTask(int[] source,int start, int end ) {
24
this.source = source;
25
this.start = start;
26
this.end = end;
27
}
28
29
30
@Override
31
protected int[] compute() {
32
//长度小于50,进行计算
33
if(source.length <= 50) {
34
long sum = 0L;
35
for(int i=start; i<end; i++) sum += nums[i];
36
return sum;
37
}
38
//长度大于50,继续划分子任务
39
int middle = start + (end-start)/2;
40 41
AddTask subTask1 = new MyTask(source,start,middle);
42
AddTask subTask2 = new MyTask(source,middle,end);
43
subTask1.fork();//递归创建子任务线程
44
subTask2.fork();
45 46
//计算完成后将两个子任务的结果合并
47
return subTask1.join() + subTask2.join();
48
}
49
}
50
}

  各种线程池的底层实现:

  一、基本线程池:

  FixedThreadPool
       CachedThreadPool
       ScheduledThreadPool
       SingleThreadPool
  二、底层创建线程池都是使用ThreadPoolExecutor类实现的,而放置任务、执行任务使用了生产者消费者模型(阻塞队列的方式)
  三、源码分析
  ThreadPoolExecutor的API:
  

ThreadPoolExecutor(int corePoolSize,//核心线程数(最小)

                   int maximumPoolSize,//最大线程数

                   long keepAliveTime, //线程运行时间

                   TimeUnit unit, //时间单位

                   BlockingQueue<Runnable> workQueue)//底层采用哪种阻塞队列来放线程任务

  各种线程池的底层实现:

  

//FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads,//初始线程数自定义
nThreads,//最大线程数自定义
0L, TimeUnit.SECONDS,//一旦启动线程池,线程永远不消失
new LinkedBlockingQueue<Runnable>());//链表阻塞队列
}

  

//CachedThreadPool(采用同步阻塞队列装任务,队列中有任务则启动新线程执行,没任务就阻塞)
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,//初始为0个线程
Integer.MAX_VALUE,//可以启动无限多线程
60L, TimeUnit.SECONDS,//60秒空闲则结束
new SynchronousQueue<Runnable>());//同步阻塞队列,有任务马上开新线程执行(容量用于为0)
}

  

//SingleThreadPool
return new ThreadPoolExecutor(1,//初始线程数为1
1,//最大线程数为1
0L, TimeUnit.SECONDS,//一旦启动线程池,线程永远不消失
new LinkedBlockingQueue<Runnable>());//链表阻塞队列
}

  

//ScheduledThreadPool
public newScheduledThreadPool(int corePoolSize){
super(corePoolSize,//初始线程数自定义
Integer.MAX_VALUE,//无限多线程数
0, NANOSECONDS,//一旦启动线程池,线程永远不消失
new DelayedWorkQueue<Runnable>());//延时阻塞队列,隔一段时间执行一次任务
}

  

  
 

Java线程池及其底层源码实现分析的更多相关文章

  1. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  2. Java线程池ThreadPoolExector的源码分析

    前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等 ...

  3. JUC(4)---java线程池原理及源码分析

    线程池,既然是个池子里面肯定就装很多线程. 如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁 线程,如此一来会大大降低系统的效率.可能出现服务器在为每个请求创建新线程和销毁 ...

  4. JAVA线程池原理与源码分析

    1.线程池常用接口介绍 1.1.Executor public interface Executor { void execute(Runnable command); } 执行提交的Runnable ...

  5. Java线程池的底层实现与使用

    前言 在我们进行开发的时候,为了充分利用系统资源,我们通常会进行多线程开发,实现起来非常简单,需要使用线程的时候就去创建一个线程(继承Thread类.实现Runnable接口.使用Callable和F ...

  6. 线程池:ThreadPoolExecutor源码解读

    目录 1 带着问题去阅读 1.1 线程池的线程复用原理 1.2 线程池如何管理线程 1.3 线程池配置的重要参数 1.4 shutdown()和shutdownNow()区别 1.5 线程池中的两个锁 ...

  7. Java ThreadPoolExecutor线程池原理及源码分析

    一.源码分析(基于JDK1.6) ThreadExecutorPool是使用最多的线程池组件,了解它的原始资料最好是从从设计者(Doug Lea)的口中知道它的来龙去脉.在Jdk1.6中,Thread ...

  8. 详解Java线程池的ctl(线程池控制状态)【源码分析】

    0.综述 ctl 是线程池源码中常常用到的一个变量. 它的主要作用是记录线程池的生命周期状态和当前工作的线程数. 作者通过巧妙的设计,将一个整型变量按二进制位分成两部分,分别表示两个信息. 1.声明与 ...

  9. Java 线程池架构原理和源码解析(ThreadPoolExecutor)

    在前面介绍JUC的文章中,提到了关于线程池Execotors的创建介绍,在文章:<java之JUC系列-外部Tools>中第一部分有详细的说明,请参阅: 文章中其实说明了外部的使用方式,但 ...

随机推荐

  1. Intellij IDEA如何在一个窗口同时打开多个Maven项目

    建立父目录,比如fatherProject,并将多个项目放入该父目录fatherProject下 File-Open...打开父目录fatherProject 引入pom.xml,打开Maven Pr ...

  2. Angularjs 通过directive实现验证两次输入是否一致的功能

    实现效果: 1> 当输入确认密码时验证: 2> 当输入密码时验证: 实现步骤: 1.页面代码: <input class="form-control" type= ...

  3. solr特点一:高亮(highlighting)

    高亮的配置 参数详细说明: hl.fl: 用空格或逗号隔开的字段列表.要启用某个字段的highlight功能,就得保证该字段在schema中是stored.如果该参数未被给出,那么就会高亮默认字段 s ...

  4. subprocess.Popen命令如何隐藏弹框

    在用PYQT编写GUI界面时,代码中有用到subprocess.Popen(),打包exe后每次遇到subprocess语句是就会弹出命令框,很是头疼, 下面是解决的办法 import subproc ...

  5. eclipse-->run as --> maven test 中文乱码

    其有一个配置参数forkMode,默认为once,即表示每次运行test时,新建一个JVM进程运行所有test. 这可能会导致乱码问题.首先将forkMode设置为never,即不新建.再运行mvn ...

  6. 在相应目录下新建或读取xml文件

    string path = AppDomain.CurrentDomain.BaseDirectory+"UserContent1.xml"; //判断相应路径下文件是否存在 不存 ...

  7. GO学习笔记 - 数据类型推导

    官方教程:https://tour.go-zh.org/basics/14 在定义一个变量却并不显式指定其类型时(使用 := 语法或者 var = 表达式语法), 变量的类型由(等号)右侧的值推导得出 ...

  8. “全栈2019”Java第一百零三章:匿名内部类详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. django 结合 OPTIONS方法 处理跨域请求(单个视图方法中)

    OPTIONS 方法比较少见,该方法用于请求服务器告知其支持哪些其他的功能和方法.通过 OPTIONS 方法,可以询问服务器具体支持哪些方法,或者服务器会使用什么样的方法来处理一些特殊资源.可以说这是 ...

  10. SpringMvc HttpMessageConverter之@ResponseBody

    我们先看HttpMessageConverter的示意图,从图片可以看出它是多么的重要.在一条必经之路截道了的感觉. 先上我的测试例子: jsp页面: <%@ page language=&qu ...