wordpress建站博客园,网站模板 jsp,wordpress配置伪静态页面,建设信用卡银行积分商城网站在 Java 并发编程中#xff0c;线程池是一种非常重要的技术。它可以有效地管理和复用线程#xff0c;提高系统的性能和资源利用率。本文将深入探讨 Java 线程池的概念、原理、使用方法以及最佳实践#xff0c;帮助读者更好地理解和应用线程池。 一、引言 在现代软件开发中线程池是一种非常重要的技术。它可以有效地管理和复用线程提高系统的性能和资源利用率。本文将深入探讨 Java 线程池的概念、原理、使用方法以及最佳实践帮助读者更好地理解和应用线程池。 一、引言 在现代软件开发中多线程编程是提高程序性能和响应性的重要手段。然而直接创建和管理线程会带来一些问题如线程创建和销毁的开销、资源浪费、线程过多导致的系统性能下降等。为了解决这些问题Java 提供了线程池技术。线程池可以预先创建一定数量的线程当有任务需要执行时从线程池中获取一个空闲线程来执行任务任务完成后线程不会被立即销毁而是返回线程池等待下一个任务。这样可以避免频繁地创建和销毁线程提高系统的性能和资源利用率。 二、线程池的概念与原理 一线程池的基本概念 线程池是一种管理线程的工具它包含了一组预先创建的线程和一个任务队列。当有任务需要执行时将任务提交到任务队列中线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务线程会进入等待状态直到有新的任务到来。当线程执行完一个任务后它会继续从任务队列中获取下一个任务或者进入等待状态等待新的任务到来。 二线程池的工作原理 线程池的创建 在创建线程池时可以指定线程池的核心线程数量、最大线程数量、任务队列的类型和大小等参数。核心线程数量是指线程池中始终保持运行的线程数量即使这些线程处于空闲状态。最大线程数量是指线程池中允许的最大线程数量当任务队列已满且核心线程都在忙碌时线程池会创建新的线程来执行任务直到线程数量达到最大线程数量。任务的提交 当有任务需要执行时可以通过线程池的execute方法或submit方法将任务提交到线程池中。execute方法用于提交一个Runnable任务没有返回值submit方法用于提交一个Callable任务有返回值。提交任务后线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。线程的执行 线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务线程会进入等待状态直到有新的任务到来。当线程执行完一个任务后它会继续从任务队列中获取下一个任务或者进入等待状态等待新的任务到来。如果线程在执行任务过程中发生异常线程池会创建一个新的线程来替代它并继续执行任务。线程池的关闭 当不再需要线程池时可以通过线程池的shutdown方法或shutdownNow方法来关闭线程池。shutdown方法会等待线程池中所有的任务执行完毕后再关闭线程池shutdownNow方法会立即停止线程池的执行并尝试中断正在执行任务的线程返回尚未执行的任务列表。 三、Java 线程池的类型与创建 一Java 中的线程池类型 FixedThreadPool固定大小线程池 FixedThreadPool是一种固定大小的线程池它在创建时指定了线程池的核心线程数量和最大线程数量并且这两个数量是相等的。当有任务提交到线程池中时如果线程池中存在空闲线程就会立即执行任务如果线程池中没有空闲线程就会将任务加入到任务队列中等待执行。特点线程数量固定不会因为任务的增加而创建新的线程也不会因为任务的减少而销毁线程。适用于需要限制线程数量的场景如服务器端的连接处理。CachedThreadPool可缓存线程池 CachedThreadPool是一种可缓存的线程池它在创建时没有指定线程池的核心线程数量和最大线程数量。当有任务提交到线程池中时如果线程池中存在空闲线程就会立即执行任务如果线程池中没有空闲线程就会创建一个新的线程来执行任务。当线程在一段时间内没有执行任务时就会被回收。特点线程数量不固定可以根据任务的数量自动调整线程数量。适用于执行大量短期任务的场景如网页爬虫。ScheduledThreadPool定时任务线程池 ScheduledThreadPool是一种用于执行定时任务的线程池它在创建时指定了线程池的核心线程数量。当有定时任务提交到线程池中时线程池会创建一个新的线程来执行任务并在任务执行完毕后将线程回收。如果在任务执行过程中发生异常线程池会创建一个新的线程来替代它并继续执行任务。特点可以执行定时任务和周期性任务。适用于需要定期执行任务的场景如定时备份数据。SingleThreadExecutor单线程线程池 SingleThreadExecutor是一种单线程的线程池它在创建时只有一个核心线程。当有任务提交到线程池中时这个核心线程会执行任务。如果任务在执行过程中发生异常线程池会创建一个新的线程来替代它并继续执行任务。特点只有一个线程在执行任务保证任务按照提交的顺序依次执行。适用于需要保证任务顺序执行的场景如日志记录。 二创建线程池的方法 使用Executors工厂类创建线程池 Java 提供了Executors工厂类来方便地创建不同类型的线程池。可以使用Executors.newFixedThreadPool、Executors.newCachedThreadPool、Executors.newScheduledThreadPool和Executors.newSingleThreadExecutor方法分别创建固定大小线程池、可缓存线程池、定时任务线程池和单线程线程池。示例代码 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 创建固定大小线程池ExecutorService fixedThreadPool Executors.newFixedThreadPool(5);// 创建可缓存线程池ExecutorService cachedThreadPool Executors.newCachedThreadPool();// 创建定时任务线程池ExecutorService scheduledThreadPool Executors.newScheduledThreadPool(3);// 创建单线程线程池ExecutorService singleThreadExecutor Executors.newSingleThreadExecutor();}
}使用ThreadPoolExecutor构造函数创建线程池 除了使用Executors工厂类创建线程池外还可以直接使用ThreadPoolExecutor构造函数来创建线程池。这样可以更加灵活地控制线程池的参数如核心线程数量、最大线程数量、任务队列的类型和大小等。示例代码 import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CustomThreadPoolExample {public static void main(String[] args) {// 创建线程池核心线程数量为 3最大线程数量为 5任务队列大小为 10任务超时时间为 1 分钟ThreadPoolExecutor threadPool new ThreadPoolExecutor(3,5,1,TimeUnit.MINUTES,new ArrayBlockingQueue(10));}
}四、线程池的任务提交与执行 一提交任务的方法 execute方法 execute方法用于提交一个Runnable任务到线程池中执行没有返回值。如果线程池中的线程数量小于核心线程数量就会创建一个新的线程来执行任务如果线程池中的线程数量等于核心线程数量就会将任务加入到任务队列中等待执行。示例代码 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ExecuteExample {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(3);executorService.execute(() - {System.out.println(Task executed by thread: Thread.currentThread().getName());});executorService.shutdown();}
}submit方法 submit方法用于提交一个Callable任务到线程池中执行有返回值。如果线程池中的线程数量小于核心线程数量就会创建一个新的线程来执行任务如果线程池中的线程数量等于核心线程数量就会将任务加入到任务队列中等待执行。当任务执行完毕后会返回一个Future对象可以通过这个对象来获取任务的执行结果。示例代码 import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class SubmitExample {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(3);FutureInteger future executorService.submit(() - {System.out.println(Task executed by thread: Thread.currentThread().getName());return 42;});try {Integer result future.get();System.out.println(Task result: result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}executorService.shutdown();}
}二任务的执行过程 线程从任务队列中获取任务 线程池中的线程会不断地从任务队列中获取任务并执行。如果任务队列中没有任务线程会进入等待状态直到有新的任务到来。当有任务提交到线程池中时线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。任务的执行 线程获取到任务后会执行任务中的代码。如果任务在执行过程中发生异常线程池会创建一个新的线程来替代它并继续执行任务。如果任务执行成功线程会继续从任务队列中获取下一个任务或者进入等待状态等待新的任务到来。任务的返回结果 如果提交的任务是一个Callable任务并且使用了submit方法提交任务那么可以通过Future对象来获取任务的返回结果。如果任务在执行过程中发生异常Future对象的get方法会抛出相应的异常。 五、线程池的参数调整与性能优化 一线程池参数的含义与调整方法 核心线程数量corePoolSize 核心线程数量是指线程池中始终保持运行的线程数量即使这些线程处于空闲状态。当有任务提交到线程池中时如果线程池中存在空闲线程就会立即执行任务如果线程池中没有空闲线程就会将任务加入到任务队列中等待执行。如果任务队列已满且核心线程都在忙碌时线程池会创建新的线程来执行任务直到线程数量达到最大线程数量。调整方法根据任务的类型和数量来调整核心线程数量。如果任务是 CPU 密集型的即任务主要消耗 CPU 资源可以将核心线程数量设置为与 CPU 核心数量相等或稍大一些以充分利用 CPU 资源。如果任务是 I/O 密集型的即任务主要消耗 I/O 资源可以将核心线程数量设置得较大一些以提高线程的并发度。最大线程数量maximumPoolSize 最大线程数量是指线程池中允许的最大线程数量。当任务队列已满且核心线程都在忙碌时线程池会创建新的线程来执行任务直到线程数量达到最大线程数量。如果任务队列已满且线程数量达到最大线程数量那么新提交的任务将被拒绝执行。调整方法根据系统的资源情况和任务的类型来调整最大线程数量。如果系统的资源比较充足可以将最大线程数量设置得较大一些以提高线程的并发度。如果系统的资源比较紧张可以将最大线程数量设置得较小一些以避免系统资源的过度消耗。任务队列workQueue 任务队列是用于存储等待执行的任务的队列。当有任务提交到线程池中时如果线程池中存在空闲线程就会立即执行任务如果线程池中没有空闲线程就会将任务加入到任务队列中等待执行。调整方法根据任务的类型和数量来选择合适的任务队列类型和大小。如果任务是 CPU 密集型的可以选择一个较小的任务队列以避免任务在队列中等待时间过长。如果任务是 I/O 密集型的可以选择一个较大的任务队列以提高线程的并发度。常见的任务队列类型有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。线程空闲时间keepAliveTime 线程空闲时间是指线程在没有任务可执行时的最大等待时间。当线程在一段时间内没有执行任务时就会被回收。如果线程空闲时间设置得过长可能会导致线程资源的浪费如果线程空闲时间设置得过短可能会导致线程频繁地创建和销毁增加系统的开销。调整方法根据任务的类型和数量来调整线程空闲时间。如果任务是短期任务可以将线程空闲时间设置得较短一些以避免线程资源的浪费。如果任务是长期任务可以将线程空闲时间设置得较长一些以减少线程的创建和销毁次数。拒绝策略rejectedExecutionHandler 拒绝策略是指当任务队列已满且线程数量达到最大线程数量时新提交的任务将被拒绝执行时采取的策略。Java 提供了四种拒绝策略分别是AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy和DiscardPolicy。调整方法根据系统的需求和任务的重要性来选择合适的拒绝策略。如果任务比较重要可以选择CallerRunsPolicy让提交任务的线程自己执行任务如果任务不太重要可以选择DiscardPolicy或DiscardOldestPolicy直接丢弃新提交的任务。 二性能优化的技巧与注意事项 合理设置线程池参数 根据任务的类型和数量来合理设置线程池的参数如核心线程数量、最大线程数量、任务队列的类型和大小等。避免设置过大或过小的参数以免影响系统的性能和资源利用率。避免任务阻塞 在任务执行过程中尽量避免任务的阻塞如 I/O 操作、数据库访问等。可以使用异步 I/O、连接池等技术来减少任务的阻塞时间提高线程的并发度。监控线程池状态 可以使用 Java 的监控工具如jconsole、VisualVM等来监控线程池的状态如线程数量、任务队列大小、任务执行时间等。根据监控结果来调整线程池的参数以提高系统的性能和资源利用率。避免线程泄漏 在任务执行过程中要注意避免线程泄漏。线程泄漏是指线程在执行任务过程中由于某些原因没有正确地释放资源导致线程一直处于运行状态无法被回收。可以使用try-with-resources语句、finally块等方式来确保资源的正确释放。考虑任务的优先级 如果任务有不同的优先级可以考虑使用优先级队列来存储任务以便高优先级的任务能够优先执行。Java 提供了PriorityBlockingQueue类来实现优先级队列。 六、线程池的应用场景与实际案例 一应用场景 网络服务器 在网络服务器中需要同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程提高服务器的并发处理能力。当有新的连接请求到来时从线程池中获取一个空闲线程来处理连接连接处理完毕后线程返回线程池等待下一个连接请求。数据库连接池 在数据库访问中频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接提高数据库访问的效率。当有数据库访问请求到来时从线程池中获取一个数据库连接来执行查询操作查询完毕后将数据库连接返回线程池等待下一个查询请求。任务调度 在任务调度中需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程提高任务调度的效率。当有定时任务需要执行时从线程池中获取一个空闲线程来执行任务任务执行完毕后线程返回线程池等待下一个定时任务。并行计算 在并行计算中需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程提高并行计算的效率。将计算任务分解为多个子任务提交到线程池中执行最后将子任务的结果合并得到最终的计算结果。 二实际案例 网络服务器案例 假设我们要开发一个简单的网络服务器能够同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程提高服务器的并发处理能力。示例代码 import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class NetworkServerExample {public static void main(String[] args) {try {// 创建服务器套接字监听端口 8080ServerSocket serverSocket new ServerSocket(8080);System.out.println(服务器启动监听端口 8080);// 创建线程池核心线程数量为 5最大线程数量为 10ExecutorService executorService Executors.newFixedThreadPool(5);while (true) {// 等待客户端连接Socket clientSocket serverSocket.accept();System.out.println(客户端连接 clientSocket.getInetAddress());// 将客户端连接处理任务提交到线程池executorService.execute(() - handleClient(clientSocket));}} catch (IOException e) {e.printStackTrace();}}private static void handleClient(Socket clientSocket) {try {// 读取客户端发送的数据java.io.BufferedReader in new java.io.BufferedReader(new java.io.InputStreamReader(clientSocket.getInputStream()));String request in.readLine();System.out.println(收到客户端请求 request);// 处理请求并发送响应java.io.PrintWriter out new java.io.PrintWriter(clientSocket.getOutputStream(), true);out.println(HTTP/1.1 200 OK);out.println(Content-Type: text/html);out.println();out.println(htmlbodyHello, World!/body/html);// 关闭客户端连接clientSocket.close();} catch (IOException e) {e.printStackTrace();}}
}数据库连接池案例 在数据库访问中频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接提高数据库访问的效率。示例代码 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class DatabaseConnectionPool {private static final int POOL_SIZE 10;private BlockingQueueConnection connectionQueue;public DatabaseConnectionPool() {try {Class.forName(com.mysql.jdbc.Driver);connectionQueue new LinkedBlockingQueue(POOL_SIZE);for (int i 0; i POOL_SIZE; i) {Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/mydb, username, password);connectionQueue.add(connection);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}public Connection getConnection() throws InterruptedException {return connectionQueue.take();}public void releaseConnection(Connection connection) {connectionQueue.add(connection);}
}任务调度案例 在任务调度中需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程提高任务调度的效率。示例代码 import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class TaskSchedulerExample {public static void main(String[] args) {ScheduledExecutorService scheduler Executors.newScheduledThreadPool(3);// 每隔 5 秒执行一次任务scheduler.scheduleAtFixedRate(() - {System.out.println(执行定时任务 System.currentTimeMillis());}, 0, 5, TimeUnit.SECONDS);}
}并行计算案例 在并行计算中需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程提高并行计算的效率。示例代码 import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class ParallelComputingExample {public static void main(String[] args) {ListInteger numbers new ArrayList();for (int i 0; i 100; i) {numbers.add(i);}ExecutorService executorService Executors.newFixedThreadPool(5);ListFutureInteger futures new ArrayList();for (Integer number : numbers) {CallableInteger task () - {return number * number;};futures.add(executorService.submit(task));}int sum 0;for (FutureInteger future : futures) {try {sum future.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}System.out.println(并行计算结果 sum);executorService.shutdown();}
}七、结论 Java 线程池是一种非常强大的并发编程工具它可以有效地管理和复用线程提高系统的性能和资源利用率。在实际应用中我们可以根据任务的类型和数量来选择合适的线程池类型并合理调整线程池的参数以达到最佳的性能效果。同时我们还需要注意避免线程泄漏、任务阻塞等问题确保线程池的稳定运行。通过合理地使用线程池我们可以轻松地实现高并发、高性能的 Java 应用程序。 文章转载自: http://www.morning.srbbh.cn.gov.cn.srbbh.cn http://www.morning.kgslc.cn.gov.cn.kgslc.cn http://www.morning.jqhrk.cn.gov.cn.jqhrk.cn http://www.morning.c7500.cn.gov.cn.c7500.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.qtwd.cn.gov.cn.qtwd.cn http://www.morning.wdjcr.cn.gov.cn.wdjcr.cn http://www.morning.yhywx.cn.gov.cn.yhywx.cn http://www.morning.kbqbx.cn.gov.cn.kbqbx.cn http://www.morning.enjoinfo.cn.gov.cn.enjoinfo.cn http://www.morning.dbnrl.cn.gov.cn.dbnrl.cn http://www.morning.jqmqf.cn.gov.cn.jqmqf.cn http://www.morning.gklxm.cn.gov.cn.gklxm.cn http://www.morning.cfpq.cn.gov.cn.cfpq.cn http://www.morning.btblm.cn.gov.cn.btblm.cn http://www.morning.ylzdx.cn.gov.cn.ylzdx.cn http://www.morning.lmhwm.cn.gov.cn.lmhwm.cn http://www.morning.smspc.cn.gov.cn.smspc.cn http://www.morning.xdfkrd.cn.gov.cn.xdfkrd.cn http://www.morning.fmqw.cn.gov.cn.fmqw.cn http://www.morning.qnyf.cn.gov.cn.qnyf.cn http://www.morning.qxxj.cn.gov.cn.qxxj.cn http://www.morning.lqznq.cn.gov.cn.lqznq.cn http://www.morning.wdhzk.cn.gov.cn.wdhzk.cn http://www.morning.skbkq.cn.gov.cn.skbkq.cn http://www.morning.tnfyj.cn.gov.cn.tnfyj.cn http://www.morning.njdtq.cn.gov.cn.njdtq.cn http://www.morning.bfjtp.cn.gov.cn.bfjtp.cn http://www.morning.kbyp.cn.gov.cn.kbyp.cn http://www.morning.hyjpl.cn.gov.cn.hyjpl.cn http://www.morning.krtky.cn.gov.cn.krtky.cn http://www.morning.ptqds.cn.gov.cn.ptqds.cn http://www.morning.fqssx.cn.gov.cn.fqssx.cn http://www.morning.hympq.cn.gov.cn.hympq.cn http://www.morning.xkyst.cn.gov.cn.xkyst.cn http://www.morning.fcwxs.cn.gov.cn.fcwxs.cn http://www.morning.dlurfdo.cn.gov.cn.dlurfdo.cn http://www.morning.hwcln.cn.gov.cn.hwcln.cn http://www.morning.cdrzw.cn.gov.cn.cdrzw.cn http://www.morning.yrskc.cn.gov.cn.yrskc.cn http://www.morning.rfldz.cn.gov.cn.rfldz.cn http://www.morning.zgpgl.cn.gov.cn.zgpgl.cn http://www.morning.kllzy.com.gov.cn.kllzy.com http://www.morning.qgghr.cn.gov.cn.qgghr.cn http://www.morning.ruifund.com.gov.cn.ruifund.com http://www.morning.tbnpn.cn.gov.cn.tbnpn.cn http://www.morning.beeice.com.gov.cn.beeice.com http://www.morning.qgmbx.cn.gov.cn.qgmbx.cn http://www.morning.znqmh.cn.gov.cn.znqmh.cn http://www.morning.bgrsr.cn.gov.cn.bgrsr.cn http://www.morning.zmqb.cn.gov.cn.zmqb.cn http://www.morning.brwnd.cn.gov.cn.brwnd.cn http://www.morning.ynlbj.cn.gov.cn.ynlbj.cn http://www.morning.bqyb.cn.gov.cn.bqyb.cn http://www.morning.pzrrq.cn.gov.cn.pzrrq.cn http://www.morning.qlxgc.cn.gov.cn.qlxgc.cn http://www.morning.pjzcp.cn.gov.cn.pjzcp.cn http://www.morning.trsmb.cn.gov.cn.trsmb.cn http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn http://www.morning.ryznd.cn.gov.cn.ryznd.cn http://www.morning.yfstt.cn.gov.cn.yfstt.cn http://www.morning.hcrxn.cn.gov.cn.hcrxn.cn http://www.morning.xpmhs.cn.gov.cn.xpmhs.cn http://www.morning.wcyr.cn.gov.cn.wcyr.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.hhnhb.cn.gov.cn.hhnhb.cn http://www.morning.gwsfq.cn.gov.cn.gwsfq.cn http://www.morning.bqpg.cn.gov.cn.bqpg.cn http://www.morning.nrrzw.cn.gov.cn.nrrzw.cn http://www.morning.fwcnx.cn.gov.cn.fwcnx.cn http://www.morning.wschl.cn.gov.cn.wschl.cn http://www.morning.yswxq.cn.gov.cn.yswxq.cn http://www.morning.smhtg.cn.gov.cn.smhtg.cn http://www.morning.rcwbc.cn.gov.cn.rcwbc.cn http://www.morning.brfxt.cn.gov.cn.brfxt.cn http://www.morning.rcmwl.cn.gov.cn.rcmwl.cn http://www.morning.rklgm.cn.gov.cn.rklgm.cn http://www.morning.fmswb.cn.gov.cn.fmswb.cn http://www.morning.jppb.cn.gov.cn.jppb.cn http://www.morning.ndpwg.cn.gov.cn.ndpwg.cn