在Spring框架中,单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。这种模式在Spring的默认bean作用域中得到了实现。当一个bean被声明为单例,Spring会创建一个实例,并在整个应用程序的生命周期内维护它。任何对该bean的后续请求都会返回相同的实例。
单例作用域是Spring中默认的bean作用域。当一个bean被声明为单例时,Spring会创建一个bean的实例,并在应用程序的整个生命周期内将其维护在应用程序上下文中。任何对该bean的后续请求都会返回同一个实例。
@Component
public class SingletonService {
public void process() {
System.out.println("Processing request by " + Thread.currentThread().getName());
}
}
@SpringBootApplication
public class SingletonDemoApplication {
@Autowired
private SingletonService singletonService;
public static void main(String[] args) {
SpringApplication.run(SingletonDemoApplication.class, args);
}
@PostConstruct
public void simulateParallelRequests() {
Runnable task = () -> singletonService.process();
for (int i = 0; i < 5; i++) {
new Thread(task).start();
}
}
}
运行示例代码会产生如下输出:
Processing request by Thread-1
Processing request by Thread-2
Processing request by Thread-3
Processing request by Thread-4
Processing request by Thread-5
每个线程都使用相同的SingletonService实例来处理请求。
尽管单例bean具有单一实例的特性,但它仍然可以有效地处理多个并行请求。这要归功于JVM如何处理多个线程以及单例bean本身的设计。
如果单例bean的方法是线程安全的,那么它就可以处理多个线程并发访问。线程安全确保多个线程可以访问共享资源而不会导致不一致的结果。
如果单例bean是无状态的(即,它不维护任何跨请求的状态),那么它天生就是线程安全的。这是因为线程之间没有共享状态,不会导致竞态条件或其他并发问题。
有状态的单例bean在方法调用间维护状态,需要特别注意以确保线程安全。开发者需要实现同步机制或使用线程局部变量,以确保每个线程都有其状态的隔离副本。
@Component
public class ThreadSafeService {
public synchronized void safeProcess() {
System.out.println("Thread-safe processing by " + Thread.currentThread().getName());
}
}
@SpringBootApplication
public class ThreadSafeDemoApplication {
@Autowired
private ThreadSafeService threadSafeService;
public static void main(String[] args) {
SpringApplication.run(ThreadSafeDemoApplication.class, args);
}
@PostConstruct
public void simulateParallelRequests() {
Runnable task = () -> threadSafeService.safeProcess();
for (int i = 0; i < 5; i++) {
new Thread(task).start();
}
}
}
运行此代码确保每个线程由于synchronized关键字而顺序处理请求:
Thread-safe processing by Thread-1
Thread-safe processing by Thread-2
Thread-safe processing by Thread-3
Thread-safe processing by Thread-4
Thread-safe processing by Thread-5