最全面的JAVA多线程知识总结
背景:
2023年经营惨淡,经历了裁员就业跳槽再就业,在找工作过程中对于知识的梳理和总结,本文总结JAVA多线程。
应用场景:
需要同时执行多个任务或处理大量并发请求时,
目前常用的场景有:
- Web服务器: 在Web服务器中,每个请求通常都是一个独立的任务,通过使用多线程可以同时处理多个请求,提高服务器的吞吐量和响应速度。
- 并行计算: 对于需要处理大量计算的任务,如图像处理、数据分析、科学计算等,可以使用多线程并行处理,充分利用多核处理器的性能优势,加快计算速度。
- 数据爬虫: 网络爬虫通常需要同时处理多个网页的下载和解析。使用多线程可以并发地下载和解析多个网页,提高爬取效率。
- 实时数据处理: 对于实时数据处理应用,如实时监控、实时日志处理等,可以使用多线程实时处理和响应事件。
- 游戏开发: 在游戏开发中,多线程可以用于实现游戏逻辑和渲染的并行处理,提高游戏性能和流畅度。
- 并发容器: Java提供了线程安全的并发容器,如ConcurrentHashMap、ConcurrentLinkedQueue等,适用于多线程环境下的高并发数据存储和访问。
- 异步编程: 使用多线程可以实现异步编程,将耗时的任务放到后台执行,保持界面的响应性,提高用户体验。
- 定时任务: 使用多线程可以实现定时任务的执行,定期执行一些需要周期性处理的任务。
- 线程池: 使用线程池可以有效地管理和复用线程资源,避免频繁创建和销毁线程,提高性能和资源利用率。
创建方法:
1、implements Runnable | extends Thread
2、ExecutorService实现类ThreadPoolExecutor
3、Executors.newFixedThreadPool
示例代码:
示例1:SimpleWebServer-模拟web服务器通过使用多线程可以同时处理多个请求
package xyz.lijiantao.study.thread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Description 在Web服务器中,每个请求通常都是一个独立的任务,通过使用多线程可以同时处理多个请求,提高服务器的吞吐量和响应速度。
* @Date 2023/7/26 14:05
* @Created by LIJIANTAO
*/
public class SimpleWebServer {
public static void main(String[] args) {
final int port = 8080;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Web server is listening on port " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("New client connected: " + clientSocket.getInetAddress());
// 创建新线程处理客户端请求
Thread requestHandlerThread = new Thread(new RequestHandler(clientSocket));
requestHandlerThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class RequestHandler implements Runnable {
private final Socket clientSocket;
public RequestHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
// 从客户端读取请求内容
String request = in.readLine();
System.out.println("Received request from client: " + request);
// 模拟处理请求的耗时任务
Thread.sleep(2000);
// 返回响应给客户端
out.println("HTTP/1.1 200 OK");
out.println("Content-Type: text/html");
out.println();
out.println("<html><body>");
out.println("<h1>Hello, Web Server!</h1>");
out.println("</body></html>");
clientSocket.close();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
}

示例2:MonitorThreadDealEfficient-模拟多线程VS单线程处理任务效率
package xyz.lijiantao.study.thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @Description 模拟多线程处理任务
* @Date 2023/7/26 10:44
* @Created by LIJIANTAO
*/
public class MonitorThreadDealEfficient {
public static void main(String[] args) throws InterruptedException {
// 创建ThreadPoolExecutor线程池
int corePoolSize = 30; // 核心线程数,表示线程池中保持活动状态的线程数量
int maxPoolSize = 50; // 最大线程数,表示线程池允许创建的最大线程数量
long keepAliveTime = 5; // 线程空闲时间,超过该时间未执行任务的线程将被回收
TimeUnit timeUnit = TimeUnit.SECONDS; // 空闲时间单位
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize, maxPoolSize, keepAliveTime, timeUnit,
new LinkedBlockingQueue<>() // 任务队列,使用无界队列LinkedBlockingQueue
);
final CountDownLatch latch = new CountDownLatch(corePoolSize);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000 * 10; i++) {
Task task = new Task(i,"multiThread");
threadPoolExecutor.submit(task);
}
// 等待所有线程执行完成
while (true){
// 判断是否还有正在执行的任务
if (threadPoolExecutor.getActiveCount() > 0) {
// System.out.println("There are still active tasks.");
} else {
System.out.println("No active tasks.");
long end = System.currentTimeMillis();
System.out.println("multiThread 执行花费时间: " + (end - start) / 1000 + "s");
// 关闭线程池
threadPoolExecutor.shutdown();
break;
}
}
long start1 = System.currentTimeMillis();
for (int i = 0; i < 1000 * 10; i++) {
Task task1 = new Task(i);
task1.run();
}
long end1 = System.currentTimeMillis();
System.out.println("single thread 执行花费时间: " + (end1 - start1) / 1000 + "s");
}
static class Task implements Runnable{
private int executeNum;
private CountDownLatch latch;
private String executeType = "single thread";
public Task(int executeNum,CountDownLatch latch){
this.executeNum = executeNum;
this.latch = latch;
}
public Task(int executeNum){
this.executeNum = executeNum;
}
public Task(int executeNum,String executeType){
this.executeNum = executeNum;
this.executeType = executeType;
}
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
finally {
// System.out.println(executeType +" Task executed times: " + (executeNum + 1) + " is running on thread " + Thread.currentThread().getName());
}
}
}
}

示例3:ParallelProcessingExample-多线程并行处理示例代码
package xyz.lijiantao.study.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @Description java多线程并行处理示例代码
* @Date 2023/7/26 14:26
* @Created by LIJIANTAO
*/
public class ParallelProcessingExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
int numThreads = 4; // 假设有4个线程并行处理任务
int numTasks = 10; // 假设有10个任务
// 创建线程池,用于并行处理任务
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
// 创建任务列表和结果列表
List<Callable<String>> tasks = new ArrayList<>();
List<Future<String>> results;
// 创建任务并添加到任务列表
for (int i = 0; i < numTasks; i++) {
final int taskId = i;
tasks.add(() -> {
// 模拟处理任务的耗时
Thread.sleep(1000);
return "Task " + taskId + " is completed by " + Thread.currentThread().getName();
});
}
// 并行处理任务并获取结果
results = executor.invokeAll(tasks);
// 关闭线程池
executor.shutdown();
// 打印任务执行结果
for (int i = 0; i < numTasks; i++) {
Future<String> result = results.get(i);
System.out.println(result.get());
}
}
}

常见的框架:
- Executor框架: Executor框架是Java标准库中提供的多线程框架,通过Executors工具类可以创建不同类型的线程池,如FixedThreadPool、CachedThreadPool、SingleThreadPool等。Executor框架提供了高级的任务执行和管理功能,适用于大部分简单的多线程任务。
- Fork/Join框架: Fork/Join框架是Java标准库中提供的用于并行计算的框架。它适用于大规模的任务划分和处理,并且可以利用多核处理器的优势来提高计算性能。
- Akka: Akka是一个开源的、基于Actor模型的并发框架。它提供了高级的并发抽象,可以让开发者更容易地编写并发、分布式和容错的应用程序。Akka是用Scala编写的,但也支持Java。
- RxJava: RxJava是ReactiveX的Java实现,它是一个异步编程库,支持响应式编程范式。RxJava可以帮助您处理异步任务、事件流和并发问题,提供了强大的工具来处理数据流和事件序列。
- Quasar: Quasar是一个基于Fiber(纤程)的并发框架,它可以让您使用更轻量级的线程(纤程)来实现并发任务。Quasar提供了对Java并发原语的增强,使得编写高效且易于维护的并发代码更加容易。
其他知识点:
1、ThreadPoolExecutor VS ThreadPool
在Java中都是用于管理线程池的类,但它们之间存在一些区别:
- 接口和实现:
ThreadPoolExecutor是Java标准库中的一个具体类,它实现了ExecutorService接口,用于管理线程池。ThreadPoolExecutor提供了丰富的线程池配置选项和管理方法,可以更加灵活地定制线程池的行为。
ThreadPool并不是Java标准库中的类,它可能是您自己实现的一个类或者某个第三方库提供的一个类。ThreadPool可能是基于ThreadPoolExecutor实现的,也可能是其他方式实现的。由于不是标准库中的类,ThreadPool可能不提供和ThreadPoolExecutor一样的配置选项和管理方法。
- 配置和灵活性:
ThreadPoolExecutor提供了丰富的配置选项,可以根据需要配置核心线程数、最大线程数、线程空闲时间、任务队列类型、拒绝策略等。这使得您可以根据具体应用场景和资源需求来定制线程池的行为。
ThreadPool可能只提供了一组简单的配置选项,可能不如ThreadPoolExecutor灵活,适用性可能相对较差。
- 可扩展性:
由于ThreadPoolExecutor是Java标准库的一部分,它是标准和通用的线程池实现。它可以直接在Java应用中使用,并且由于是标准库的一部分,未来的Java版本也会继续支持。
ThreadPool的实现可能是特定于某个库或项目的,如果使用第三方库提供的ThreadPool,则需要确保其可靠性和可维护性。
综上所述,ThreadPoolExecutor是Java标准库中用于管理线程池的标准实现,提供了丰富的配置选项和管理方法,可以在Java应用中直接使用。而ThreadPool可能是自定义的线程池实现或者某个第三方库提供的线程池实现,需要根据具体情况进行选择。一般情况下,优先考虑使用标准库中的ThreadPoolExecutor,以便获得更好的可扩展性和维护性。
2、Callable VS Runable
返回值:
Callable接口的call()方法可以返回一个结果,而Runnable接口的run()方法没有返回值。异常抛出:
call()方法声明了可能抛出Exception异常,而run()方法没有声明抛出任何异常。使用方式: 在多线程编程中,
Runnable一般用于执行无返回值的任务,而Callable用于执行有返回值的任务执行方式: 在Java中,
Runnable通常通过Thread类的构造函数传递给线程对象,并通过start()方法来启动线程。而
Callable通常通过ExecutorService的submit()方法提交给线程池来执行,并通过Future对象获取返回结果。
总结:
你只管努力,剩下的交给时间。加油,打工人!
文本完
最全面的JAVA多线程知识总结的更多相关文章
- 最全面的Java多线程用法解析
1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable ...
- JAVA多线程知识总结(二)
本文是承接上一篇文章:JAVA多线程知识总结(一) 四.Java多线程的阻塞状态与线程控制 上文已经提到线程阻塞的集中具体类型.下面主要看引起JAVA线程阻塞的方法 1,join()-----让一个 ...
- 最强最全的Java后端知识体系
目录 最全的Java后端知识体系 Java基础 算法和数据结构 Spring相关 数据库相关 方法论 工具清单 文档 @(最强最全的Java后端知识体系) 最全的Java后端知识体系 最全的Java后 ...
- JAVA 多线程知识总结(一)
一,线程的生命周期以及五种基本状态 关于JAVA线程的生命周期,首先看一下下面这张图 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌握了. Ja ...
- 海纳百川而来的一篇相当全面的Java NIO教程
目录 零.NIO包 一.Java NIO Channel通道 Channel的实现(Channel Implementations) Channel的基础示例(Basic Channel Exampl ...
- 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)
构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...
- 面试求职中需要了解的Java多线程知识
Java中多线程的实现方式 在java的历史版本中,有两种创建多线程程序的方法 1) 通过创建Thread类的子类来实现(Thread类提供了主线程调用其它线程并行运行的机制) 主要步骤: 自定义类继 ...
- 031 一次全面的java复习
一:相关概念 1.面向对象的三个特征 封装,继承,多态,这个应该是人人皆知,有时候也会加上抽象. 2.多态的好处 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性.简单的说 ...
- 非常全面的java基础笔试题
下面是java基础笔试题,当时我去笔试,做了1个小时(80道选择题,后面的简答题就没时间做了),结果很吓人,太挫了,最后被面试官忽悠去培训去了,呵呵.我偷偷把面试题弄了下来,用来学习吧,也希望能对你们 ...
- Java多线程知识整理
多线程 1. 多线程基础 多线程状态转换图 普通方法介绍 yeild yeild,线程让步.是当前线程执行完后所有线程又统一回到同一起跑线.让自己或者其他线程运行,并不是单纯的让给其他线程. join ...
随机推荐
- 第6章. 部署到GithubPages
依托GitHub Pages 服务,可以把 vuepress 编译后的 博客静态文件 放置到该平台,那么就可以把静态页面发布出来,就会实现了不用购买云服务器就可以发布静态页面的功能. 1. 创建仓库 ...
- [双目视差] 立体匹配算法推理 - SGBM算法(二)
文章目录 立体匹配算法推理 - SGBM算法(二) 一.SGM算法 二. 后处理 立体匹配算法推理 - SGBM算法(二) 一.SGM算法 SGM算法的全称为Semi-Global Matching, ...
- Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round) 小记
在机房其它人都有许多的橙名小号后我终于大号上橙了(果然还是太菜了),写篇博客记录一下. 计数水平太弱,赛场最后 5 分钟乱糊了一个 F 的做法,后来发现其它人做法都短好多. A & B &am ...
- i < sqrt(n) 和 i*i < n 那一种写法更加高效?
这两种写法效率依赖处理器.编译器和标准库.一般来说循环内的重复操作的性能差于循环外的单次操作. 参考文献 Which is more efficient to use in a for loop, i ...
- boot-admin开源项目中有关后端参数校验的最佳实践
我们在项目开发中,经常会对一些参数进行校验,比如非空校验.长度校验,以及定制的业务校验规则等,如果使用if/else语句来对请求的每一个参数一一校验,就会出现大量与业务逻辑无关的代码,繁重不堪且繁琐的 ...
- OFFICE-Excel_在只有清单没有定额人材机的情况下筛选工程量的操作
目的 一个来自东莞的项目需要清单里面所有的电线电缆的量和价,但是由于东莞市的投标清单只需要清单报价即可,没有定额,也就没有人材机,所以就只能依靠清单来剔除量,但是有几个问题,众所周知电线电缆这种材料一 ...
- 2020-09-01:mysql里什么是检查点、保存点和中间点?
福哥答案2020-09-01: 检查点checkpoint:批量刷盘.在一定程度上代表了刷到磁盘时日志所处的日志序列号(LSN)位置.标记重做日志中已经完成刷到磁盘的位置点,如果缓冲池中有很多重做日志 ...
- 2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和。 n比较大,10的5次方。 来自美团。3.26笔试。
2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和. n比较大,10的5次方. 来自美团.3.26笔试. 答案2022-06-23: 要i还是不要i,递归. ...
- 用go设计开发一个自己的轻量级登录库/框架吧(业务篇)
用go设计开发一个自己的轻量级登录库/框架吧(业务篇) 本篇会讲讲框架的登录业务的实现.实现三种登录模式: 同一用户只能登录一次 同一用户多次登录多token 同一用户多次登录共享一个token 源码 ...
- windows server 2012 2019启动 开机自动启动 项设置
1.第一种方法:打开运行功能,运行shell:startup,打开管理员用户启动项目录.将想要设置成开机自启的程序快捷方式添加到其中即可,或者删除其中快捷方式即可取消开机自启.2.第二种方法:打开系统 ...