线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销

优点:(面试题)
可重复使用已有线程,避免对象创建、消亡和过度切换的性能开销。
避免创建大量同类线程所导致的资源过度竞争和内存溢出的问题。
支持更多功能,比如延迟任务线程池(newScheduledThreadPool)和缓存线程池(newCachedThreadPool)等。

创建方式:
有两种:ThreadPoolExecutor 和 Executors

1、ThreadPoolExecutor 的使用

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue(100));
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
// 执行线程池
System.out.println("Hello, Java.");
}
});

ThreadPoolExecutor构造方法:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);

构造参数说明

//① corePoolSize
//线程池中的核心线程数,默认情况下核心线程一直存活在线程池中,
// 如果将 ThreadPoolExecutor 的 allowCoreThreadTimeOut 属性设为 true,
// 如果线程池一直闲置并超过了 keepAliveTime 所指定的时间,核心线程就会被终止。

//② maximumPoolSize
// 线程池中最大线程数,如果活动的线程达到这个数值以后,后续的新任务将会被阻塞(放入任务队列)。

//③ keepAliveTime
//线程池的闲置超时时间,默认情况下对非核心线程生效,如果闲置时间超过这个时间,非核心线程就会被回收。
// 如果 ThreadPoolExecutor 的 allowCoreThreadTimeOut 设为 true 的时候,核心线程如果超过闲置时长也会被回收。

//④ unit
//配合 keepAliveTime 使用,用来标识 keepAliveTime 的时间单位。

// ⑤ workQueue
// 线程池中的任务队列,使用 execute() 或 submit() 方法提交的任务都会存储在此队列中。

//⑥ threadFactory 为线程池提供创建新线程的线程工厂。

//⑦ rejectedExecutionHandler
//线程池任务队列超过最大值之后的拒绝策略,RejectedExecutionHandler 是一个接口,里面只有一个 rejectedExecution 方法,可在此方法内添加任务超出最大值的事件处理。ThreadPoolExecutor 也提供了 4 种默认的拒绝策略:
//new ThreadPoolExecutor.DiscardPolicy():丢弃掉该任务,不进行处理
//new ThreadPoolExecutor.DiscardOldestPolicy():丢弃队列里最近的一个任务,并执行当前任务
//new ThreadPoolExecutor.AbortPolicy():直接抛出 RejectedExecutionException 异常
//new ThreadPoolExecutor.CallerRunsPolicy():既不抛弃任务也不抛出异常,直接使用主线程来执行此任务

代码演示:

(1)test1

public static void test1() throws ExecutionException, InterruptedException {
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(1, 1, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue(2));
threadPoolExecutor.allowCoreThreadTimeOut(true); //线程池执行方法 execute()
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-Hello java!");
}
}); //线程池执行方法 submit() 可以接收线程池执行的返回值。
Future<Object> future = threadPoolExecutor.submit(new Callable<Object>() {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+"-Hello china!");
return "success";
}
});
System.out.println(future.get());
}

(2)test2

public static void test2(){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,10L,TimeUnit.SECONDS,
new LinkedBlockingQueue(2),new MyThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0;i<10;i++){
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" wake up!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
static class MyThreadFactory implements ThreadFactory{
private AtomicInteger count = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("myThread"+count.addAndGet(1));
return t;
}
}

(3)test3

//shutdown & shutdownNow
//shutdown():不会立即终止线程池,而是要等所有任务队列中的任务都执行完后才会终止。执行完 shutdown 方法之后,线程池就不会再接受新任务了。
//shutdownNow():执行该方法,线程池的状态立刻变成 STOP 状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,执行此方法会返回未执行的任务。
public static void test3(){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,10,10,TimeUnit.SECONDS,new LinkedBlockingDeque<>(10));
threadPoolExecutor.execute(()->{
for (int j=0; j<5 ;j++){
System.out.println("i m " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
});
// threadPoolExecutor.shutdown();
threadPoolExecutor.shutdownNow(); threadPoolExecutor.execute(()->{
System.out.println("i m stop!");
});
}

(4)test4

public static void test4(){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1,10,TimeUnit.SECONDS,new LinkedBlockingDeque<>(1),new ThreadPoolExecutor.DiscardPolicy());
threadPoolExecutor.allowCoreThreadTimeOut(true);
for (int i=0;i<10;i++) {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "wake up!");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
} //线程池第 1 次执行任务时,会新创建任务并执行;第 2 次执行任务时,因为没有空闲线程所以会把任务放入队列;
//第 3 次同样把任务放入队列,因为队列最多可以放两条数据,所以第 4 次之后的执行都会被舍弃(没有定义拒绝策略),于是就打印了 3 次线程名称。

总结:

线程池的工作原理:
当线程池中有任务需要执行时,线程池会判断如果线程数量没有超过核心数量就会新建线程池进行任务执行,
如果线程池中的线程数量已经超过核心线程数,这时候任务就会被放入任务队列中排队等待执行;
如果任务队列超过最大队列数,并且线程池没有达到最大线程数,就会新建线程来执行任务;
如果超过了最大线程数,就会执行拒绝执行策略。
线程池可通过 submit() 来调用执行,从而获得线程执行的结果,也可以通过 shutdown() 来终止线程池。

java学习笔记 - 线程池(一)的更多相关文章

  1. Java学习笔记 线程池使用及详解

    有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...

  2. java学习之线程池的实现

    package com.gh.threadpoor; import java.util.concurrent.ExecutorService; import java.util.concurrent. ...

  3. Java学习:线程池

    线程池 线程池概念:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多的资源. 线程池:容器-->集合(ArrayList,Hash ...

  4. 【多线程】Android多线程学习笔记——线程池

    Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...

  5. Java 学习笔记 线程控制

    题目一 本质上来说,线程是不可控制的,线程的执行是由CPU资源分配决定的,我们无法干预系统CPU的资源分配,但我们可以增加条件来让线程按照我们的预想顺序来执行. 比如.如果当前的执行的线程不满足我们所 ...

  6. java学习笔记 线程的实现与同步

    2019.4.2 线程实现的两种方式 继承线程,复写其中的run方法 实现runnable接口,复写run方法 使用: MyThread target = new MyThread(); new Th ...

  7. Java学习笔记--线程day01

    线程的概念:一个线程是进程的顺序执行流: 同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈.线程在切换时负荷小,因此,线程也被称为轻负荷进程.一个进程中可以有多个线程. ...

  8. Java学习笔记——线程

    线程: 定义:线程是程序内的一个单一的顺序控制流程,也被称为“轻型进程(lightweight process)” 或“执行上下文(execution context )” 线程用于分隔任务 线程类似 ...

  9. java学习笔记14--多线程编程基础1

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...

随机推荐

  1. 基于官方postgres docker镜像制作自己的镜像

    1.Dockerfile FROM library/postgres MAINTAINER wenbin.ouyang #初始化PostgreSQL ENV POSTGRES_USER root EN ...

  2. CF293E Close Vertices 点分治+树状数组

    开始zz写了一个主席树,后来发现写个树状数组就行~ #include <cstdio> #include <vector> #include <algorithm> ...

  3. Controllers的使用

    代码 angularjs.html <!doctype html> <html> <head> <meta charset="UTF-8" ...

  4. python3 类的属性、方法、封装、继承及小实例

    Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法. 对象可以包含任意数量和类型的数据. p ...

  5. 使用R进行方差分析

    eff=c(58.2,52.6,56.2,41.2,65.3,60.8,49.1,42.8,54.1,50.5,51.6,48.4,60.1,58.3,70.9,73.2,39.2,40.7,75.8 ...

  6. JavaScript 函数相关属性

    1.name 既函数名 function test(){ console.log("Haha") }; console.log(test.name)//test 2.length属 ...

  7. js中filter过滤用法总结

    定义和用法 filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素. 注意: filter() 不会对空数组进行检测. 注意: filter() 不会改变原始数组 ...

  8. DeepFaceLab错误:DLL Load failed 找不到指定模块!

    这个错误不知道多少人遇到了,我反正是看到过不少次了.但是一直没有花时间去研究. 今日有空帮群友远程了一下,虽然搞了一会儿,最终还是搞定了,分享一下经验. ​ 问题描述:在执行2号脚本,视频转图片的时候 ...

  9. OpenCV学习笔记(11)——Canny边缘检测

    了解Canny边缘检测的概念 1.原理 Canny边缘检测是一种非常流行的边缘检测算法,是 John F.Canny在1986年提出的.它是一个有很多步构成的算法 1)噪声去除 使用5*5的高斯滤波器 ...

  10. 无法在WEB服务器上启动调试,Web 服务器配置不正确

    访问IIS元数据库失败 思考可能是次序出了问题,解决 1.打开CMD,进入 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 2.输入 aspnet_regi ...