• 技术文章 >Java >java教程

    spring中的bean是线程安全的吗?

    (*-*)浩(*-*)浩2019-09-12 16:14:59转载1881
    spring 中的 bean 是线程安全的吗?

    Spring 不保证 bean 的线程安全。

    默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。如下面的例子

    计数类

    package constxiong.interview.threadsafe;
     
    /**
     * 计数类
     * @author ConstXiong
     * @date 2019-07-16 14:35:40
     */
    public class Counter {
     
    	private int count = 0;
    	
    	public void addAndPrint() {
    		try {
    			Thread.sleep(10);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(++count);
    	}
    }

    spring 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    	    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
            
    	<bean id="counter" class="constxiong.interview.threadsafe.Counter" />
    	
    </beans>

    测试类

    package constxiong.interview.threadsafe;
     
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
     
    public class CounterTest {
    	
    	public static void main(String[] args) {
    		final ApplicationContext context = new ClassPathXmlApplicationContext("spring_safe.xml");
     
    		for (int i = 0; i < 10; i++) {
    			new Thread(){
    				@Override
    				public void run() {
    					Counter counter = (Counter)context.getBean("counter");
    					for (int j = 0; j < 1000; j++) {
    						counter.addAndPrint();
    					}
    				}
    			}.start();
    		}
    		
    	}
    	
    }

    打印结果开头和结尾

    1
    5
    7
    4
    2
    6
    3
    8
    9
    .
    .
    .
    9818
    9819
    9820
    9821
    9822
    9823
    9824
    9825

    期望打印出的最大值应该是 10000

    修改 spring 配置文件,把 bean 的作用域改为 prototype

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    	    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    	<bean id="counter" class="constxiong.interview.threadsafe.Counter" scope="prototype"/>
    </beans>

    测试结果输出10个 1000

    java-11.png即每个线程都创建了一个 Counter 对象,线程内独自计数,不存在线程安全问题。但是不是我们想要的结果,打印出 10000。

    所以 spring 管理的 bean 的线程安全跟 bean 的创建作用域和 bean 所在的使用环境是否存在竞态条件有关,spring 并不能保证 bean 的线程安全。

    以上就是spring中的bean是线程安全的吗?的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:CSDN,如有侵犯,请联系admin@php.cn删除
    专题推荐:spring java
    上一篇:细说Spring——AOP详解(AOP概览) 下一篇:Java程序为何“编译一次,到处运行”?
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• Spring Boot中整合Sharding-JDBC读写分离的介绍(附代码)• 如何在SpringBoot中集成JWT鉴权(附代码)• springboot如何解决跨域问题?• Spring lazy-init原理的分析(代码示例)
    1/1

    PHP中文网