ThreadLocal示例Demo 代码分离

本文介绍了一个使用ThreadLocal实现多线程程序的示例,通过查询不同人物的身高信息,展示了如何利用ThreadLocal来简化多线程编程并实现代码的分离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量示例为每一个查询创建一个线程,ThreadLocal提供局部变量的思想实现代码分离



如图写一个小功能实现查询小明 小红 小江 身高的代码。



package demo;

public class Main {

	static String[] names = new String[] { "小红", "小明", "小江", "小红", "小明", "小江"};
	static int index = 0;

	public static void main(String[] args) {

		for (int i = 0; i < names.length; i++) {
			Thread t = new Thread() {
				@Override
				public void run() {
					// 为每一个查询创建一个线程
					ThreadLocalUtils.DATA.set(this.getName());
					// 用SQLSearch将数据查询的逻辑部分实现代码分离
					System.out.println(new SQLSearch().run());
				}

			};
			t.setName(names[index++]);
			t.start();

		}
	}
}
package demo;
public class SQLSearch implements MyRunnable {

	public String run() {
		//返回查询结果
		return search(ThreadLocalUtils.DATA.get());
	}

	// 模拟查询
	private String search(String name) {
		String result=null;
		// Sql
		if (name.equals("小明")) {
			result = (name + "185身高");
		}
		if (name.equals("小红")) {
			result = (name + "160身高");
		}
		if (name.equals("小江")) {
			result = (name + "180身高");
		}
		return result;

	}
}
package demo;
public interface MyRunnable {

	public String run();
}

package demo;

public class ThreadLocalUtils {
	public static final ThreadLocal<String> DATA = new ThreadLocal<String>();
}





<think>好的,我现在需要帮助用户解决如何使用Spring Boot、MyBatis-Plus和dynamic-datasource-spring-boot-starter来构建一个包含分库分表和动态数据源的Demo项目。首先,我应该回顾用户提供的引用内容,看看里面有没有相关的信息。 用户提供的引用中提到了dynamic-datasource-spring-boot-starter可以支持多数据源,适用于多种场景,包括纯粹多库、读写分离等。引用3和5提到了整合MyBatis-Plus和dynamic-datasource的依赖配置,还有示例代码结构。不过,分库分表的具体实现可能需要更多的信息,比如如何路由数据到不同的库和表。 接下来,我需要考虑分库分表的常见实现方式。通常,分库分表可以通过中间件如ShardingSphere,或者通过应用层自己实现路由逻辑。而dynamic-datasource-spring-boot-starter主要处理动态数据源切换,可能结合分库分表策略需要在代码中自定义路由。 用户需要示例代码,所以需要给出具体的步骤:依赖配置、数据源配置、分库分表策略、动态数据源切换方式、MyBatis-Plus的集成以及业务层的使用示例。 首先,确认依赖是否正确。根据引用5,dynamic-datasource的版本是3.4.1,MyBatis-Plus是3.1.2。不过可能需要使用更新的版本,但用户示例可能沿用这些版本。 然后,配置文件中需要设置多个数据源,比如master、slave1、slave2等,每个对应不同的数据库。分库分表的话,可能需要根据某个字段(比如用户ID)的哈希值或者取模来决定使用哪个数据源和表名。 动态数据源的核心是AbstractRoutingDataSource,而dynamic-datasource已经封装了这部分,可以通过@DS注解来切换数据源。分表的话,可能需要在SQL中动态替换表名,比如使用MyBatis的拦截器或者自定义注解。 在编写示例代码时,需要演示如何在Service层使用@DS注解切换数据源,以及如何根据分片键计算数据源和表名。例如,根据用户ID的奇偶性选择不同的数据源和表后缀。 可能还需要注意事务管理的问题,确保在切换数据源时事务能正确处理。此外,分库分表后的主键生成策略也需要考虑,比如使用分布式ID生成器。 最后,生成相关问题,考虑用户可能遇到的性能优化、事务处理、动态添加数据源等问题。</think>以下是一个基于Spring Boot、MyBatis-Plus和dynamic-datasource-spring-boot-starter实现分库分表与动态数据源的示例指南: --- ### **1. 环境准备** **依赖配置**(pom.xml): ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` --- ### **2. 数据源配置** **application.yml**: ```yaml spring: datasource: dynamic: primary: master # 默认数据源 strict: false # 允许未匹配到数据源时回退到默认 datasource: master: url: jdbc:mysql://localhost:3306/db0?useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver slave1: url: jdbc:mysql://localhost:3306/db1?useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ``` --- ### **3. 分库分表策略** #### **分库逻辑**(按用户ID分库): ```java public class ShardingContext { private static final ThreadLocal<String> DB_KEY = new ThreadLocal<>(); public static void setDbKey(String dbKey) { DB_KEY.set(dbKey); } public static String getDbKey() { return DB_KEY.get(); } public static void clear() { DB_KEY.remove(); } } // 在AOP中根据分片键计算数据源 @Aspect @Component public class DataSourceAspect { @Before("@annotation(ds)") public void before(DS ds) { Long userId = getCurrentUserId(); // 实际业务中获取分片键 String dbKey = "slave" + (userId % 2); ShardingContext.setDbKey(dbKey); } } ``` #### **分表逻辑**(按用户ID分表): ```java public class UserTableSharding { public static String getTableSuffix(Long userId) { return "_" + (userId % 4); // 分为4张表:user_0 ~ user_3 } } ``` --- ### **4. 动态数据源切换** **Service层使用@DS注解**: ```java @Service @DS("#dbKey") // 动态占位符从ShardingContext获取 public class UserServiceImpl extends ServiceImpl<UserMapper, User> { public User getUserById(Long userId) { // 分表查询 String tableName = "user" + UserTableSharding.getTableSuffix(userId); return baseMapper.selectByTable(userId, tableName); } } // Mapper接口 public interface UserMapper extends BaseMapper<User> { @Select("SELECT * FROM ${tableName} WHERE id = #{userId}") User selectByTable(@Param("userId") Long userId, @Param("tableName") String tableName); } ``` --- ### **5. 核心配置类** **启动类注解**: ```java @SpringBootApplication @MapperScan("com.example.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` --- ### **6. 事务管理** 使用`@Transactional`时需指定事务管理器: ```java @Transactional(rollbackFor = Exception.class, transactionManager = "dynamicTransactionManager") public void saveUser(User user) { // 分库分表保存逻辑 } ``` --- ### **注意事项** 1. **分片键计算**:需保证分片键(如用户ID)的均匀分布 2. **分布式ID生成**:建议使用雪花算法(`MyBatis-Plus`内置`@TableId(type = IdType.ASSIGN_ID)`) 3. **跨库查询**:尽量避免跨库事务操作 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值