一.方式
- 1.将bean声明为多例
- 2.将成员变量放在ThreadLocal
- 3. 同步锁(影响系统吞吐量)
二.代码示例
1.声明为多例
@Configuration
public class MainConfig {
@Bean
@Scope("prototype")
public UserService userService(){
return new UserService();
}
}
package com.learning.beanthreadsafe;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class UserService {
private String username;
public String welcome(String username){
this.username = "welcome:" + username;
// 处理业务
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.username;
}
}
package com.learning.beanthreadsafe;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class Run {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// 线程一
UserService bean1 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean1.welcome("张三"));
}).start();
// 线程二
UserService bean2 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean2.welcome("李四"));
}).start();
}
}
2.将成员变量放在ThreadLocal
package com.learning.beanthreadsafe;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
@Configuration
public class MainConfig {
@Bean
public UserService userService(){
return new UserService();
}
}
package com.learning.beanthreadsafe;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class UserService {
private ThreadLocal<String> username = new ThreadLocal<>();
public String welcome(String username){
this.username.set("welcome:" + username);
// 处理业务
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.username.get();
}
}
package com.learning.beanthreadsafe;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class Run {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// 线程一
UserService bean1 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean1.welcome("张三"));
}).start();
// 线程二
UserService bean2 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean2.welcome("李四"));
}).start();
}
}
3.同步锁
package com.learning.beanthreadsafe;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
@Configuration
public class MainConfig {
@Bean
public UserService userService(){
return new UserService();
}
}
package com.learning.beanthreadsafe;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class UserService {
private String username;
public synchronized String welcome(String username){
this.username = "welcome:" + username;
// 处理业务
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.username;
}
}
package com.learning.beanthreadsafe;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author wangyouhui
* @Description 单例是否线程安全
**/
public class Run {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// 线程一
UserService bean1 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean1.welcome("张三"));
}).start();
// 线程二
UserService bean2 = applicationContext.getBean(UserService.class);
new Thread(()->{
System.out.println(bean2.welcome("李四"));
}).start();
}
}