好的提升设计师网站,网站建设与管理 教材,购物网站修改文案,网络培训课堂app常见的线程类型包括用户线程#xff08;User Threads#xff09;、守护线程#xff08;Daemon Threads#xff09;、主线程#xff08;Main Thread#xff09;、工作线程#xff08;Worker Threads#xff09;和线程池中的线程。
一、用户线程#xff08;User Thread…常见的线程类型包括用户线程User Threads、守护线程Daemon Threads、主线程Main Thread、工作线程Worker Threads和线程池中的线程。
一、用户线程User Threads
特点
用户线程是普通的Java线程通常由程序员显式创建。用户线程在程序运行期间一直存在直到它们完成任务或程序终止。
代码示例
public class UserThreadExample {public static void main(String[] args) {Thread userThread new Thread(() - {for (int i 0; i 5; i) {System.out.println(User thread running: i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});userThread.start();}
}2、守护线程Daemon Threads
特点
守护线程是在后台运行的线程它们通常用于为其他线程提供服务。当所有用户线程都结束时JVM会自动终止守护线程并退出。即使守护线程没有执行完任务也会被JVM强制退出所以主要业务一定不能放在守护线程中执行守护线程通常用于执行一些辅助任务如垃圾回收、日志记录等。
代码示例
public class DaemonThreadExample {public static void main(String[] args) {Thread daemonThread new Thread(() - {while (true) {System.out.println(Daemon thread running...);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});daemonThread.setDaemon(true); // 设置为守护线程就这一句就够了daemonThread.start();// 主线程休眠一段时间后结束try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
}解释
创建一个新的线程daemonThread并将其设置为守护线程。守护线程无限循环运行每秒打印一条消息。主线程休眠5秒后结束此时JVM会自动终止守护线程也会被终止。
3、主线程Main Thread
特点
主线程是每个Java应用程序的入口点它是JVM在启动时自动创建的第一个线程。主线程负责执行main方法中的代码。当主线程结束时如果还有其他用户线程在运行JVM会继续运行这些线程。
代码示例
public class MainThreadExample {public static void main(String[] args) {System.out.println(Main thread started);Thread userThread new Thread(() - {System.out.println(User thread running...);try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}});userThread.start(); // 用户线程启动实际上就是主线程干的事情System.out.println(Main thread ending);}
}解释
主线程执行main方法中的代码。创建并启动一个用户线程userThread。主线程在启动用户线程后继续执行打印之后就结束了。用户线程会继续运行直到完成任务。
4、工作线程Worker Threads
特点
工作线程通常用于执行具体的任务它们可以是用户线程或守护线程。工作线程通常由线程池管理用于处理任务队列中的任务。工作线程可以提高应用程序的并发性和性能。
代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WorkerThreadExample {public static void main(String[] args) {ExecutorService executor Executors.newFixedThreadPool(2); // 创建固定大小的线程池for (int i 0; i 5; i) {int taskId i;executor.submit(() - {System.out.println(Task taskId is running on thread Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}executor.shutdown(); // 关闭线程池}
}解释
创建一个固定大小为2的线程池executor。提交5个任务到线程池每个任务在执行时会打印任务ID和当前线程名称。调用shutdown方法关闭线程池等待所有任务完成。
5、线程池中的线程
特点
线程池中的线程是由线程池管理的它们可以重复使用减少了创建和销毁线程的开销。线程池可以控制并发线程的数量避免过多的线程消耗系统资源。线程池通常用于处理大量的短期任务。
代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executor Executors.newCachedThreadPool(); // 创建可缓存线程池for (int i 0; i 10; i) {int taskId i;executor.submit(() - {System.out.println(Task taskId is running on thread Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}executor.shutdown(); // 关闭线程池}
}解释
创建一个可缓存线程池executor它会根据需要创建新的线程。提交10个任务到线程池每个任务在执行时会打印任务ID和当前线程名称。调用shutdown方法关闭线程池等待所有任务完成。
6、线程分类总结
1、用户线程普通的Java线程由程序员显式创建。 2、守护线程后台线程用于提供服务当所有用户线程结束时自动终止。 3、主线程JVM自动创建的第一个线程执行main方法中的代码。 4、工作线程用于执行具体任务的线程通常由线程池管理。 5、线程池中的线程由线程池管理的线程可以重复使用减少开销。
7、springboot常见线程类型
1、主线程Main Thread
1、概述
这是Spring Boot应用启动时由JVM创建的第一个线程。主线程负责启动Spring Boot应用加载配置初始化Spring容器等。
2、创建时机
应用启动时由JVM自动创建。
代码示例
SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}2、Tomcat/NIO线程(接受客户端请求用)
1、概述
如果你的Spring Boot应用使用了嵌入式的Tomcat服务器Tomcat会创建多个线程来处理HTTP请求。这些线程通常是NIO线程非阻塞线程可异步负责接收客户端请求并处理响应。
2、创建时机
当Spring Boot应用启动并初始化嵌入式Tomcat服务器时。
配置文件示例 无需编码仅配置即可不配置也可以会有默认配置。
server:port: 8080tomcat:max-threads: 200 # 最大线程数min-spare-threads: 10 # 最小空闲线程数3、定时任务线程Scheduled Tasks
1、概述
如果你在Spring Boot应用中使用了定时任务如Scheduled注解Spring Boot会创建一个或多个线程来执行这些定时任务。这些线程通常由TaskScheduler管理。
2、创建时机
当Spring Boot应用启动并初始化定时任务时。
代码示例
Configuration
EnableScheduling
public class SchedulerConfig {
}Component
public class ScheduledTasks {Scheduled(fixedRate 5000) // 自动创建定时任务线程监听并执行public void performTask() {System.out.println(Executing scheduled task at LocalDateTime.now());}
}4、异步任务线程Async Tasks
1、概述
如果你在Spring Boot应用中使用了异步方法如Async注解Spring Boot会创建一个或多个线程来执行这些异步任务。这些线程通常由TaskExecutor管理。
这个在附录中在详细说明。
5、自定义线程
1、概述
你可以在Spring Boot应用中手动创建和管理线程例如通过实现Runnable接口或继承Thread类。
2、创建时机
在你需要的时候手动创建。
代码示例
Component
public class CustomThreadExample {PostConstructpublic void startCustomThread() {Thread customThread new Thread(() - {while (true) {System.out.println(Custom thread running at LocalDateTime.now());try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}});customThread.start();}
}附录
异步任务线程Async Tasks
1、概述
如果你在Spring Boot应用中使用了异步方法如Async注解Spring Boot会创建一个或多个线程来执行这些异步任务主线程不会阻塞会继续执行后面的代码。这些线程通常由TaskExecutor管理。使用异步任务使用EnableAsync开启后主方法等配置入口在需要的方法上添加Async注解即可。
2、异步任务线程的作用
1、提高响应性
异步任务线程可以在后台执行耗时的操作而不阻塞主线程或请求处理线程。这样主线程可以继续处理其他请求提高系统的整体响应性。
2、优化资源利用
对于耗时较长的任务如果使用同步方式处理可能会占用宝贵的线程资源导致其他任务无法及时处理。异步任务线程可以将这些任务移到后台执行释放主线程资源。
3、并发处理
异步任务线程可以并行处理多个任务提高系统的并发处理能力。这对于需要处理大量并发请求的应用尤其重要。
3、异步任务特点
1、异步任务线程异步任务在单独的线程中执行不会阻塞主线程。 2、立即返回异步方法调用会立即返回一个CompletableFuture对象主线程可以继续执行其他任务。 3、回调机制使用thenAccept等方法注册回调函数这些回调函数在异步任务完成时被调用被线程池的其他线程调用不会阻塞主线程。
4、常见的异步任务场景
1、邮件发送
发送邮件是一个耗时操作通常需要几秒钟甚至更长时间。使用异步任务线程可以在后台发送邮件而不会阻塞主线程。
2、文件上传和下载
文件上传和下载操作通常涉及大量的I/O操作使用异步任务线程可以避免阻塞主线程提高系统的响应性。
3、数据处理和计算
对于复杂的数据处理和计算任务使用异步任务线程可以将这些任务移到后台执行释放主线程资源。
4日志记录
日志记录操作通常需要写入磁盘使用异步任务线程可以避免阻塞主线程提高系统的性能。
5、异步任务线程与异步请求处理的区别
前者是优化请求响应速度把不重要或耗时的事情放在后台慢慢执行主线程可以继续干其他事情或直接返回的一种处理方式后者是并行可同时接受客户端的多个请求两者完全不是一回事需要注意下。
1、异步任务线程
用于处理耗时较长的后台任务。通常由开发人员手动创建和管理。使用Async注解和TaskExecutor来实现。 即用于处理耗时较长的后台任务提高系统的响应性和并发处理能力。
2、异步请求处理
用于处理HTTP请求的异步响应。通常由Web框架如Spring MVCspringboot自动支持。使用CompletableFuture、DeferredResult等异步API来实现。 即用于处理HTTP请求的异步响应通常由Web框架自动支持。
6、如何使用异步任务
1、EnableAsync
EnableAsync注解只需要在一个配置类上启用一次即可在整个应用程序中启用异步任务的支持。即开启后会告诉Spring框架扫描并管理带有Async注解的方法。
代码示例
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;Configuration
EnableAsync
public class AsyncConfig {// 配置类可以包含其他Bean和配置
}2、Async
1、Async注解用于标记那些需要异步执行的方法上。注意方法必须在一个Spring管理的Bean中否则不会扫描到。 2、Async标记的方法将在异步任务线程中执行不会阻塞当前线程而是立即返回一个Future对象或CompletableFuture对象。这个Future对象现在是无法获取结果的只能通过定义回调的方式用于异步任务完成后再去通知调用的线程当然如果无需等待结果的也可以直接忽略返回结果。
3、异步线程池
默认情况下Spring是使用一个简单的线程池来执行异步任务。你也可以自定义线程池注入spring容器中以更好地控制异步任务的执行。
3.1、自定义线程池示例
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;Configuration
EnableAsync // 开启异步任务
public class AsyncConfig {Bean // 注入线程池public ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(5);executor.setQueueCapacity(100);executor.setThreadNamePrefix(Async-);executor.initialize();return executor;}
}3.2、控制器示例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;RestController
public class AsyncController {Autowiredprivate AsyncService asyncService;GetMapping(/send-email)public String sendEmail(RequestParam String recipient, RequestParam String message) {// 调用异步方法CompletableFutureString result asyncService.sendEmail(recipient, message);// 处理异步结果result.thenAccept(response - { // 定义的回调方法不会阻塞主线程主线程会定义完成之后直接跳过该方法往后执行。在异步任务完成后真正执行回调方法代码的是线程池中的线程。System.out.println(Response: response); // 异步任务完成后由线程池中的线程执行主线程不会执行。});return Request accepted, email will be sent asynchronously;}
}3.3、异步方法
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;Service
public class AsyncService {Asyncpublic CompletableFutureString sendEmail(String recipient, String message) {// 模拟耗时操作try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}// 发送邮件System.out.println(Email sent to recipient : message);return CompletableFuture.completedFuture(Email sent successfully);}
}解释一下 1、异步方法的调用
在AsyncController的sendEmail方法中调用asyncService.sendEmail方法。sendEmail方法被标记为Async因此它会在一个异步任务线程中执行。方法调用会立即返回一个CompletableFutureString对象标识异步任务的结果对象。这个对象现在是无法获取执行结果的因为还没有执行完成需要想要调用线程得到响应可以通过定义回调的方式在异步任务完成后再通知调用的线程。 2、处理异步结果使用result.thenAccept(response - { ... })方法来处理异步任务的结果。thenAccept方法注册一个回调函数当异步任务完成时回调函数会被调用并传入任务的结果。这个回调函数在异步任务线程中执行不会阻塞主线程。 3、立即返回响应AsyncController的sendEmail方法在调用异步方法后立即返回一个字符串Request accepted, email will be sent asynchronously。这个响应告诉客户端请求已经被接受邮件将在后台异步发送。
学海无涯苦作舟