----@原作者-----线程池和进程池

线程池(ThreadPool)
线程池详解

  1. 线程池的作用
    线程池是一种线程使用模式,它主要解决两个问题:

重复利用线程:避免频繁创建和销毁线程,减少系统开销。
控制线程数量:限制线程的最大并发数,避免系统资源过度消耗。
其他优势包括:

提高响应速度:重用线程避免了线程创建的延迟。
提高线程的可管理性:统一管理,方便监控。
2. 线程池的创建
2.1 使用Executors工厂方法
Java提供了Executors类,其中包含多个静态工厂方法来创建不同类型的线程池:

ExecutorService executorService = Executors.newFixedThreadPool(2); // 这里的线程池里面的线程数量为2
1
常用的工厂方法包括:

newFixedThreadPool(int nThreads): 创建固定大小的线程池
newCachedThreadPool(): 创建可缓存的线程池
newSingleThreadExecutor(): 创建单线程的线程池
newScheduledThreadPool(int corePoolSize): 创建可以执行定时任务的线程池
2.2 手动创建ThreadPoolExecutor(拓展)
对于更精细的控制,可以直接使用ThreadPoolExecutor类:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
new LinkedBlockingQueue()
);
1
2
3
4
3. 线程池的使用
3.1 提交任务
可以通过execute()方法提交Runnable任务:

executorService.execute(new Runnable() {
@Override
public void run() {
// 任务代码
}
});
1
2
3
4
5
6
或者使用submit()方法提交Callable任务(可以有返回值)。

3.2 关闭线程池
shutdown(): 温和地关闭线程池,等待所有任务完成。
shutdownNow(): 立即关闭线程池,尝试中断正在执行的任务。
executorService.shutdown();
// 或
// executorService.shutdownNow();
1
2
3
4. 依赖
线程池相关的类都在java.util.concurrent包中,是Java标准库的一部分,不需要额外的依赖。

主要用到的类:

java.util.concurrent.ExecutorService
java.util.concurrent.Executors
java.util.concurrent.ThreadPoolExecutor
5. 线程池的参数
使用ThreadPoolExecutor时,可以设置以下参数:

corePoolSize: 核心线程数
maximumPoolSize: 最大线程数
keepAliveTime: 线程空闲时间
workQueue: 工作队列,用于存放任务
threadFactory: 线程工厂,用于创建线程
handler: 拒绝策略,当任务太多时如何处理
6. 注意事项
避免使用Executors创建线程池,因为它可能导致OOM(内存溢出)。推荐直接使用ThreadPoolExecutor。
合理设置线程池大小,考虑CPU核心数、内存大小等因素。
注意监控线程池的状态,及时调整参数。
记得在应用程序结束前关闭线程池。
7. 示例代码解析
ExecutorService executorService = Executors.newFixedThreadPool(2);
1
创建了一个固定大小为2的线程池。

for (int i = 0; i < 5; i++){
// 创建并提交任务
}
1
2
3
循环创建5个任务并提交给线程池。

executorService.shutdown();
1
关闭线程池,等待所有任务完成。

这个示例展示了如何创建线程池、提交任务和关闭线程池的基本操作。

  1. 具体实例

连接池
数据库连接池详解

  1. 连接池的作用
    数据库连接池主要解决以下问题:

提高性能:避免频繁地创建和关闭数据库连接,减少系统开销。
资源管理:限制数据库连接的数量,防止数据库服务器过载。
提高可用性:预先创建连接,减少获取连接的等待时间。
连接重用:允许多个请求共享同一个连接,提高资源利用率。
2. 连接池的实现(基于提供的代码)
2.1 使用 Druid 连接池
private static DruidDataSource ds;

static {
ds = new DruidDataSource();
ds.setDriverClassName(“com.mysql.cj.jdbc.Driver”);
ds.setUrl(“jdbc:mysql://localhost:3306/jdbc_study?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true”);
ds.setUsername(“root”);
ds.setPassword(“root”);
ds.setMaxActive(20); // 最大连接数
ds.setInitialSize(5); // 初始化连接数
}
1
2
3
4
5
6
7
8
9
10
11
这段代码初始化了 Druid 连接池,设置了数据库驱动、URL、用户名、密码等基本信息,以及最大连接数和初始连接数。

2.2 获取连接
public static Connection getConnection() throws Exception {
return ds.getConnection();
}
1
2
3
这个方法从连接池中获取一个连接。当调用此方法时,如果池中有可用连接,就直接返回;如果没有,可能会创建新的连接(取决于池的配置)。

  1. 连接池的优势
    性能提升:重用连接减少了创建和销毁连接的开销。
    资源控制:可以限制最大连接数,防止数据库过载。
    响应速度:预创建连接减少了等待时间。
    统一管理:集中管理数据库连接,便于监控和调优。

  2. 应用场景
    高并发web应用:大量用户同时访问数据库时。
    数据密集型应用:需要频繁数据库操作的场景。
    分布式系统:多个服务需要共享数据库资源时。
    微服务架构:每个微服务可能需要独立的数据库连接池。

  3. 连接池的关键参数
    MaxActive:最大活跃连接数
    InitialSize:初始连接数
    MinIdle:最小空闲连接数
    MaxWait:获取连接最大等待时间

  4. 最佳实践
    合理设置池大小:根据系统并发量和数据库性能调整。
    监控连接池状态:关注连接使用情况,及时调整参数。
    使用预编译语句:可以配合连接池使用,进一步提高性能。
    及时释放连接:使用完毕后及时将连接返回池中。

  5. 注意事项
    避免连接泄露:确保在 finally 块中关闭连接。
    定期检查空闲连接:移除长时间不用的连接。
    考虑使用连接池框架:如 Druid、HikariCP 等,它们提供了更多高级特性。

  6. 代码中的改进点
    可以考虑将数据库配置信息外部化,例如放在配置文件中。
    添加更多的连接池配置,如最小空闲连接数、连接最大存活时间等。
    实现一个关闭连接池的方法,在应用程序结束时调用。
    通过使用连接池,您的应用程序可以更高效地管理数据库连接,提高性能和可扩展性。在实际应用中,需要根据具体场景调整连接池的参数,以达到最佳效果。

  7. 代码参考示例
    package socket;

import com.alibaba.druid.pool.DruidDataSource;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBUtil {
// 静态连接池
private static DruidDataSource ds;

//数据库工具类
static{
    /*
    try{
        // 反射机制获取类对象
        Class.forName("com.mysql.cj.jdbc.Driver");
        //
    }catch (Exception e){
        e.printStackTrace();
    }*/
    // 实例化连接池
    ds = new DruidDataSource();
    ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
    String databaseName = "jdbc_study";
    ds.setUrl("jdbc:mysql://localhost:3306/"+databaseName+"?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true");
    ds.setUsername("root");
    ds.setPassword("root");
    ds.setMaxActive(20);  // 最大连接数

    ds.setInitialSize(5); // 初始化连接数
}

// 静态方法获取连接
// 之所以使用throw Exception,是为了让调用者处理异常,而不是创建者处理异常
public static Connection getConnection() throws Exception{
    // 在静态块中加载驱动

    /*// 返回获取的连接
    String databaseName = "jdbc_study";
    return DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/"+databaseName+"?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true",
            "root",
            "root"
    );*/
    // 返回连接池中的连接
    return ds.getConnection();
}

}

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值