Java多线程&&线程池
Posted itLaity
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程&&线程池相关的知识,希望对你有一定的参考价值。
生命无罪,健康万岁,我是laity。
我曾七次鄙视自己的灵魂:
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。
初始化线程的 4 种方式
- 继承Thread
- 实现Runnable接口
- 实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
- 线程池
继承Thread
public static void main(String[] args) throws ExecutionException, InterruptedException
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
*/
Thread01 thread01 = new Thread01();
thread01.start(); // 启动线程
public static class Thread01 extends Thread
@Override
public void run()
System.out.println("Thread当前线程" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println(i);
实现Runnable接口
public static void main(String[] args) throws ExecutionException, InterruptedException
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
*/
Runnable01 runnable01 = new Runnable01();
new Thread(runnable01).start();
public static class Runnable01 implements Runnable
@Override
public void run()
System.out.println("Runnable当前线程" + Thread.currentThread().getId());
int i = 12 / 2;
System.out.println(i);
实现Callable接口 + FutureTask
public static void main(String[] args) throws ExecutionException, InterruptedException
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
*/
FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
new Thread(futureTask).start();
// 等待整个线程执行完成,获取的返回结果
Integer integer = futureTask.get();
System.out.println("Callable返回结果" + integer);
public static class Callable01 implements Callable<Integer>
@Override
public Integer call() throws Exception
System.out.println("Callable当前线程" + Thread.currentThread().getId());
return 14 / 2;
线程池
常见的 4 种线程池
这里我使用Executors工具类可以帮我们创建的几种常见线程池
newFixedThreadPool
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
* - 为什么用线程池 1、2、3,太浪费资源,尤其是高并发系统;
* - 将所有的多线程异步任务都交给线程池执行。
* - 降低资源的消耗
* - 提高响应速度
* - 提高线程的可管理性
*/
// 给线程池直接提交任务 - 保证当前系统中只有一两个,每个异步任务交给线程池
// service.submit()
// service.execute();
service.execute(new Runnable01());
// Executors工具类可以帮我们创建的几种常见线程池
// Executors.newFixedThreadPool() // 固定大小,core=max,都不可回收;创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static class Runnable01 implements Runnable
@Override
public void run()
System.out.println("Runnable当前线程" + Thread.currentThread().getId());
int i = 12 / 2;
System.out.println(i);
newCachedThreadPool
Executors.newCachedThreadPool() // 核心线程为0,所有线程都可回收;创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newScheduledThreadPool
Executors.newScheduledThreadPool() // 定时任务线程池;创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor
Executors.newSingleThreadExecutor() // 单线程的线程池,后台从队列中获取任务顺序逐一执行;创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
原生线程池
public static void main(String[] args) throws ExecutionException, InterruptedException
// 原生创建线程池
/**
* 七大参数
* int corePoolSize, 核心线程数量;线程池,创建好以后就准备就绪的线程数量,就等待来接收异步任务来执行
* int maximumPoolSize, 最大线程数量;控制资源
* long keepAliveTime, 存活时间;如果当前正在运行的线程数量大于核心线程数量。
* 释放空闲的线程资源(maximumPoolSize-corePoolSize),只要线程空闲大于指定的keepAliveTime;
* TimeUnit unit, 时间单位
* BlockingQueue<Runnable> workQueue, 阻塞队列;如果任务有很多, 大于maximumPoolSize的任务就会放到队列里面。
* 只要有线程空闲,就会去队列里面抽取出新的任务继续执行。
* new LinkedBlockingQueue<>(); 默认是Integer的最大值
* ThreadFactory threadFactory, 线程的创建工厂。
* RejectedExecutionHandler handler 如果队列满了,按照我们指定的拒绝策略拒绝执行任务。
*
* 工作顺序:
* 运行流程:
* 1、线程池创建,准备好 core 数量的核心线程,准备接受任务
* 2、新的任务进来,用 core 准备好的空闲线程执行。
* (1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
* (2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
* (3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到 core 大小
* (4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策略进行处理
* 3、所有的线程创建都是由指定的 factory 创建的。
*/
// Executors.defaultThreadFactory() 默认的线程工厂
// new ThreadPoolExecutor.AbortPolicy() 丢弃拒绝策略 可自行查看源码,根据业务需求自行选用。
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 200,
10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10000),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
executor.execute(new Runnable01());
public static class Runnable01 implements Runnable
@Override
public void run()
System.out.println("Runnable当前线程" + Thread.currentThread().getId());
int i = 12 / 2;
System.out.println(i);
个人总结
分析4中创建线程的优缺点
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
* - 为什么用线程池 1、2、3,太浪费资源,尤其是高并发系统;
* - 将所有的多线程异步任务都交给线程池执行。
* - 降低资源的消耗
* - 提高响应速度
* - 提高线程的可管理性
* 1、使用:
* 1)、Executors 工具类
* public static ExecutorService service = Executors.newFixedThreadPool(10);
* service.execute(new Runnable01());
* 2)、new ThreadPoolExecutor(); 原生
* 区别:
* 1、2没有返回值:主进程无法获取线程的运算结果。不适合当前场景
* 1、2、3不能控制资源:主进程可以获取线程的运算结果,但是不利于控制服务器中的线程资源。可以导致 服务器资源耗尽。
* 4可以,性能稳定。
*/
线程池的七大参数
/**
* 七大参数
* int corePoolSize, 核心线程数量;线程池,创建好以后就准备就绪的线程数量,就等待来接收异步任务来执行
* int maximumPoolSize, 最大线程数量;控制资源
* long keepAliveTime, 存活时间;如果当前正在运行的线程数量大于核心线程数量。
* 释放空闲的线程资源(maximumPoolSize-corePoolSize),只要线程空闲大于指定的keepAliveTime;
* TimeUnit unit, 时间单位
* BlockingQueue<Runnable> workQueue, 阻塞队列;如果任务有很多, 大于maximumPoolSize的任务就会放到队列里面。
* 只要有线程空闲,就会去队列里面抽取出新的任务继续执行。
* new LinkedBlockingQueue<>(); 默认是Integer的最大值
* ThreadFactory threadFactory, 线程的创建工厂。
* RejectedExecutionHandler handler 如果队列满了,按照我们指定的拒绝策略拒绝执行任务。
*
* 工作顺序:
* 运行流程:
* 1、线程池创建,准备好 core 数量的核心线程,准备接受任务
* 2、新的任务进来,用 core 准备好的空闲线程执行。
* (1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
* (2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
* (3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到 core 大小
* (4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策略进行处理
* 3、所有的线程创建都是由指定的 factory 创建的。
*/
所有代码
package com.laity.gulimall.search.thread;
import java.util.concurrent.*;
/**
* @author: Laity
* @Project: JavaLaity
* @Package: com.laity.gulimall.search.thread.ThreadTest
* @Date: 2022年10月20日 18:13
* @Description: 线程回顾
*/
public class ThreadTest
// 给线程池直接提交任务 - 保证当前系统中只有一两个,每个异步任务交给线程池
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException
/**
* 1、继承Thread
* 2、实现Runnable接口
* 3、实现Callable接口 + FutureTask(可以拿到返回值,可以处理异常) jdk1.5
* 4、线程池
* - 为什么用线程池 1、2、3,太浪费资源,尤其是高并发系统;
* - 将所有的多线程异步任务都交给线程池执行。
* - 降低资源的消耗
* - 提高响应速度
* - 提高线程的可管理性
* 1、使用:
* 1)、Executors 工具类
* public static ExecutorService service = Executors.newFixedThreadPool(10);
* service.execute(new Runnable01());
* 2)、new ThreadPoolExecutor(); 原生
* 区别:
* 1、2没有返回值
* 1、2、3不能控制资源;4可以,性能稳定。
*/
Thread01 thread01 = new Thread01();
thread01.start(); // 启动线程
Runnable01 runnable01 = new Runnable01();
new Thread(runnable01).start();
FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
new Thread(futureTask).start();
// 等待整个线程执行完成,获取的返回结果
Integer integer = futureTask.get();
System.out.println("Callable返回结果" + integer);
// 给线程池直接提交任务 - 保证当前系统中只有一两个,每个异步任务交给线程池
// service.submit()
// service.execute();
service.execute(new Runnable01());
// 原生创建线程池
/**
* 七大参数
* int corePoolSize, 核心线程数量;线程池,创建好以后就准备就绪的线程数量,就等待来接收异步任务来执行
* int maximumPoolSize, 最大线程数量;控制资源
* long keepAliveTime, 存活时间;如果当前正在运行的线程数量大于核心线程数量。
* 释放空闲的线程资源(maximumPoolSize-corePoolSize),只要线程空闲大于指定的keepAliveTime;
* TimeUnit unit, 时间单位
* BlockingQueue<Runnable> workQueue, 阻塞队列;如果任务有很多, 大于maximumPoolSize的任务就会放到队列里面。
* 只要有线程空闲,就会去队列里面抽取出新的任务继续执行。
* new LinkedBlockingQueue<>(); 默认是Integer的最大值
* ThreadFactory threadFactory, 线程的创建工厂。
* RejectedExecutionHandler handler 如果队列满了,按照我们指定的拒绝策略拒绝执行任务。
*
* 工作顺序:
* 运行流程:
* 1、线程池创建,准备好 core 数量的核心线程,准备接受任务
* 2、新的任务进来,用 core 准备好的空闲线程执行。
* (1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
* (2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
* (3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到 core 大小
* (4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策略进行处理
* 3、所有的线程创建都是由指定的 factory 创建的。
*/
// Executors.defaultThreadFactory() 默认的线程工厂
// new ThreadPoolExecutor.AbortPolicy() 丢弃拒绝策略 可自行查看源码,根据业务需求自行选用。
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 200,
10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10000),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
executor.execute(new Runnable01());
// Executors工具类可以帮我们创建的几种常见线程池
// Executors.newCachedThreadPool() // 核心线程为0,所有线程都可回收;创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
// Executors.newFixedThreadPool() // 固定大小,core=max,都不可回收;创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
// Executors.newScheduledThreadPool() // 定时任务线程池;创建一个定长线程池,支持定时及周期性任务执行。
// Executors.newSingleThreadExecutor() // 单线程的线程池,后台从队列中获取任务顺序逐一执行;创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
public static class Thread01 extends Thread
@Override
public void run()
System.out.println("Thread当前线程" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println(i);
public static class Runnable01 implements Runnable
@Override
public void run()
System.out.println("Runnable当前线程" + Thread.currentThread().getId());
int i = 12 / 2;
System.out.println(i);
public static class Callable01 implements Callable<Integer>
@Override
public Integer call() throws Exception
System.out.println("Callable当前线程" + Thread.currentThread().getId());
return 14 / 2;
以上是关于Java多线程&&线程池的主要内容,如果未能解决你的问题,请参考以下文章
JUC并发编程 共享模式之工具 ThreadPoolExecutor 多线程设计模式 -- 异步模式之工作线程(定义饥饿 & 解决饥饿 & 线程池创建多少线程数目合适)
定时任务 & 定时线程池 ScheduledThreadPoolExecutor