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. ADB server didn't ACK问题,连上手机问题(转)

    出现如下情况 ADB server didn't ACK* failed to start daemon * 解决办法: 方法一: (1)查看任务管理器,关闭所有adb.exe,或者运行->cm ...

  2. IPA文件的自动化生成和无线分发

    1. IPA的无线分发 iOS应用开发测试过程中,通过无线网络进行IPA包的分发将是非常便捷的,于是也就有了类似testflightapp之类的平台.对于这一功能,我们也可以自己实现,只需要一个简单的 ...

  3. [react002] component基本用法

    1 什么是component 设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件. 这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少 ...

  4. 10-10Linux的文件操作函数以及所需头文件

    Linux的基本文件操作函数     Linux通过相应的对文件的IO函数来实现对文件的操作,这些函数通常被称作"不带缓冲的IO",这是因为他们都是通过调用Linux的内核调用来实 ...

  5. .Net core 2.0的数据初始化

    在StartUp.cs里面,添加Seed方法 public static void Seed(IApplicationBuilder applicationBuilder) { using (var ...

  6. Asp.NetCore取配置信息

    本文简单介绍Asp.NetCore取自定义配置信息的方法,要取配置信息首先得有配置文件. 1, 本例新建了一个TimeOut.json配置文件,和其对应的一个TimeOut类 2, 首先在Startu ...

  7. 将网页发布到远程windows server

    1.在vs下利用文件系统发布asp.net文件 2.将生成的所有文件打包成ZIP 3.将zip文件复制并解压到远程windows server的自己创建的文件夹下 4.在windows server上 ...

  8. JAVA实现长连接(含心跳检测)Demo

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的.       如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端:       Client通过持有Sock ...

  9. Luogu4551 最长异或路径

    题目链接:戳我 emmmmmmmmmm异或一个数两次等于没有操作对吧...所以我们按照前缀的异或和,建一个01trie.....然后之后.....直接在树上贪心地找能和它每一位不一样的数....然后. ...

  10. AHOI2012 信号塔 | 最小圆覆盖模板

    题目链接:戳我 最小圆覆盖. 1.枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为0的圆. 2.枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点 ...