What

A generic class

Variables can be stored in ThreadLocal and then pulled out for use

role

  1. Thread concurrency: Used in multi-threaded concurrency scenarios
  2. Passing data: Common variables can be passed in different components within the same thread using the same ThreadLocal
  3. Thread isolation: Variables of each thread are independent of each other

The ThreadLocal class is used to provide local variables within a thread. This type of variable ensures that each thread’s variables are independent of other threads. ThreadLocal is of private static type and is used to associate the thread context.

The main function is: to provide local variables within the thread, different threads do not interfere with each other, only within the life cycle of the thread, reduce the complexity of common variable transfer between multiple functions or components within the same thread.

Why

Differences between threadLocal and synchronized

Both threadLocal and synchronized are used for multithreaded concurrency

sychronized threadLocal
The principle of Time for space, provide only one variable, let different threads queue access Space for time, for each thread to provide a copy of the variable, so as to achieve simultaneous access without interference
focus Synchronization of resources accessed by multiple threads Data isolation between multiple threads, so that the program has higher concurrency

HOW

Unsafe instance – Dynamic table name

The following code comes from the dynamic table name configuration of Mybatis Plus

  1. The configuration file

Set dynamicTableName, the table name passed from the foreground, to the table you want to access

Public class MybatisPlusConfig {public static String dynamicTableName; @Bean public PaginationInterceptor paginationInterceptor() { ... tableNameHandlerMap.put("tableName", (metaObject, sql, tableName) -> dynamicTableName); . }}Copy the code

Here static constants are used, here thread-unsafe ****

Public static String dynamicTableName;Copy the code

  1. interface

Thread.sleep(3000); To be able to show the problem

@ GetMapping ("/dynamicTableNameByStatic ") @ ApiOperation (value = "dynamic table name - Static," notes = "use Static, by changing the name of the table, ") public JsonResult dynamicTableNameByStatic(String tableName) throws InterruptedException { MybatisPlusConfig.DYNAMIC_TABLE_NAME.set(tableName); Thread.sleep(3000); List<User> userList = userService.list(); Log.info (" data in {} {}", tableName, userlist.toString ()); return JsonResult.ok().add(tableName, userList); }Copy the code
  1. Multithreading problem

Request 1 Request “user_1”

Request 2 request “user_2”

Request 2 changes the value of the static variable

This will cause a problem with the data obtained in request 1 (tableName has been modified)

Data inconsistency results

The 16:53:19 2020-08-04. 32756-366 the INFO [nio - 8191 - exec - 9] com. Ybj. Mysql. Controller. UserController: thread as follows: Http-nio-8191-exec-9, access table name: user_1, actual access table name: user_2Copy the code

ThreadLocal

  1. The configuration file

Use ThreadLocal to hold shared variables

It then takes the value from ThreadLocal

Public class MybatisPlusConfig {public static final threadLocal <String> DYNAMIC_TABLE_NAME = new ThreadLocal<>(); @Bean public PaginationInterceptor paginationInterceptor() { ... tableNameHandlerMap.put("tableName", (metaObject, sql, tableName) ->DYNAMIC_TABLE_NAME.get() ); . }}Copy the code
  1. interface
@ GetMapping ("/dynamicTableNameByThreadLocal ") @ ApiOperation (value = "dynamic table name - ThreadLocal," notes = "by changing the name of the table, Query different database ") public JsonResult dynamicTableNameByThreadLocal (String tableName) throws InterruptedException { MybatisPlusConfig.DYNAMIC_TABLE_NAME.set(tableName); Thread.sleep(3000); List<User> userList = userService.list(); Log.info (" data in {} {}", tableName, userlist.toString ()); return JsonResult.ok().add(tableName, userList); }Copy the code

The data here is thread-isolated and there are no problems