Spring 框架(Spring Framework)之事务管理、单元测试、单例的高并发安全问题等

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Spring 框架(Spring Framework)之事务管理、单元测试、单例的高并发安全问题等

Spring 中的事务管理

Spring支持两种事务管理方式:编程式事务和声明式事务。官方大力推荐使用声明式事务。

  • 编程式事务:将业务代码和事务代码放在一起书写,它的耦合性太高,开发中不使用
  • 声明式事务:

    • 声明式事务是建立在 AOP 的基础上的。

      其本质是在方法前后进行拦截,在方法开始之前创建事务,在方法结束后根据执行情况提交或回滚事务。

    • 声明式事务的优点:可以将事务代码和业务代码完全分离开发,然后通过配置的方式实现运行时组装运行。
    • 声明式事务的不足:只能作用到方法级别,无法像编程式事务那样可以作用到代码块级别


Spring 中事务管理相关 API

Spring中的事务控制主要就是通过这三个API实现的:

  • PlatformTransactionManager 接口:事务管理器,负责事务的管理,其子类负责具体工作
  • TransactionDefinition 接口:定义了事务的一些相关参数
  • TransactionStatus 接口:代表事务运行的一个实时状态

三者的关系:事务管理器 通过读取 事务定义参数 进行事务管理,然后会产生一系列的 事务状态


PlatformTransactionManager 接口:

  • Spring进行事务管理的一个根接口,使用其实现类做事务管理器(增强的事务处理的功能)
  • 接口方法:

    // 获取事务的状态信息
    TransactionStatus getTransaction(TransactionDefinition def)
    // 提交事务
    void commit(TransactionStatus status)
    // 回滚事务
    void rollback(TransactionStatus status)
  • 常用实现类:

    • DataSourceTransactionManager :使用 JDBC 和 MyBatis 进行持久化数据时使用
    • JpaTransactionManager :使用 JPA 进行持久化时使用(jpa,hibernate)
    • HibernateTransactionManager :使用Hibernate进行持久化数据时使用
    • JtaTransactionManager :事务跨越多个事务管理源【分布式事务】时使用


TransactionStatus 接口 :

  • 事务运行的一个实时状态
  • 接口方法

    // 是否是新事物
    boolean isNewTransaction()
    // 是否有回滚点
    boolean hasSavepoint()
    // 设置为只回滚事务
    void setRollbackOnly()
    // 是否是只回滚事务
    boolean isRollbackOnly()
    // 刷新事务状态 
    void flush()
    // 事务是否完成
    boolean isCompleted()


TransactionDefinition 接口:

  • 事务的定义信息(事事务隔离级别,传播行为,是否只读事务,超时时间等)

clip_image058

  • 事务隔离级别

    • Spring中配置事务,支持所有的4中隔离级别
    • 默认值:自动选择当前数据库合适的配置项
    • // 事务隔离级别相关【不设置事务隔离级别,可能引发脏读、不可重复读、幻读】
      ISOLATION_READ_UNCOMMITTED    读未提交    mysq1支持四种,默认可重复度
      ISOLATION_READ COMMITTED    读已提交    oracle支持两种(读己提交和串行化),默认是读已提交
      ISOLATION_REPEATABLE READ    可重复度
      ISOLATION SERIALIZABLE        串行化
  • 事务传播行为:描述多个方法嵌套调用时,被调用方法对事务的支持

    • PROPAGATION_REQUIRED = 0(必须有事务,这是默认值)

      如果存在一个事务,则加入到当前事务。如果没有事务则开启一个新的事务。

    • PROPAGATION_SUPPORTS = 1(支持有事务)

      如果存在一个事务,则加入到当前事务。如果没有事务则非事务运行。

    • PROPAGATION_MANDATORY = 2(强制有事务,自己还不负责创建)

      如果存在一个事务,则加入到当前事务。如果没有事务,则抛出异常。

    • PROPAGATION_REQUIRES_NEW = 3(必须有新的)

      总是开启一个新的事务。如果存在一个事务,则将这个存在的事务挂起,重新开启一个新的事务。

    • PROPAGATION_NOT_SUPPORTED = 4(不支持有事务)

      总是非事务地执行,并挂起任何存在的事务。

    • PROPAGATION_NEVER = 5(强制不要事务,自己还不负责挂起)

      总是非事务地执行,如果存在一个活动事务,则抛出异常

    • PROPAGATION_NESTED = 6(嵌套事务)

      如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务, 则开启一个新的事务。

      内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。

      而内层事务操作失败并不会引起外层事务的回滚

  • 是否只读事务

    isReadOnly : true | false(默认)

    只读事务: 只能查询,不能增 删 改。只读事务只能用于查询方法

  • 事务超时时长

    TIMEOUT_DEFAULT = -1 :事务的超时时间,需要底层数据库支持才能使用此配置,默认值是 -1,代表无限制。

    超时时间:使用默认值


声明式事务(xml 配置事务)

基于XML的方式完成声明式事务配置:

  • 配置事务管理器交给Spring容器管理(切面类)
  • 配置事务通知
  • 配置事务的AOP
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
             http://www.springframework.org/schema/aop
             http://www.springframework.org/schema/aop/spring-aop.xsd
             http://www.springframework.org/schema/tx
             http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--包扫描-->
    <context:component-scan base-package="cn.test"></context:component-scan>
    <!--自定义的java对象:注解-->

    <!--第三方jar包中的对象:xml-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///heima23"></property>
    </bean>

    <!--配置Spring中的事务-->
    <!--1、事务管理器交给容器管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2、配置事务通知。配置service层中所有类中所有方法,对事务的要求(支持) 
            id="advice" :表示IOC容器中真正的通知对象的id
            transaction-manager="transactionManager" :表示指定当前要对哪个事务管理器进行配置
            如果事务管理器在IOC容器中的id为transactionManager,此配置可以省略。
    -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--
                <tx:method :指定目标对象中切入点的方法名指定方法对事务的要求
                    name :方法名称。支持通配符 *
                    isolation :事务的隔离级别
                    timeout :超时时间
                    propagation :传播行为(REQUIRED)
                    read-only :是否只读事务(false)
            -->
            <tx:method name="save*" propagation="REQUIRED" read-only="false"></tx:method>
            <tx:method name="update*"></tx:method>
            <tx:method name="delete*"></tx:method>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
            <tx:method name="*"></tx:method>
        </tx:attributes>
    </tx:advice>
    <!--3、事务的AOP配置-->
    <aop:config>
        <!--切入点表达式-->
        <aop:pointcut id="pt" expression="execution(* cn.test.service.impl.*.*(..))"/>
        <!--配置切面。<aop:advisor只有在spring的声明式事务配置时才能使用-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
    </aop:config>
</beans>


声明式事务(注解)

开启事务注解支持(xml 方式)

  • 在XML配置文件中,开启事务注解的支持:事务注解驱动
  • 在XML配置文件中,创建事务管理器交给容器管理
  • 在需要事务的类或者方法上,使用 @Transactional 注解配置事务
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--包扫描-->
    <context:component-scan base-package="cn.test"></context:component-scan>

    <!--开启事务注解的支持-->
    <tx:annotation-driven></tx:annotation-driven>

    <!--事务管理器交给容器管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--自定义的java对象:注解-->

    <!--第三方jar包中的对象:xml-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///test"></property>
    </bean>
</beans>


开启事务注解支持(配置类方式)

  • @EnableTransactionManagement:标注在配置类上,开启事务注解支持
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;

@Configuration
@ComponentScan(basePackages = "cn.test")
@EnableTransactionManagement
public class SpringConfig {

    /**
     * 创建datasource
     */
    @Bean
    public DataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        dataSource.setUrl("jdbc:mysql:///test");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return dataSource;
    }

    /**
     * 创建jdbctemplate
     *  1、从容器中获取datasource
     *  2、调用方法
     */
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    /**
     * 创建事务管理器
     */
    @Bean
    public PlatformTransactionManager getManager(DataSource dataSource) {
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }
}


声明式事务注解的使用

  • @Transactional:配置事务

    常用属性:

    • rollbackFor 属性:设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚

      • 指定单一异常类:@Transactional(rollbackFor=Exception.class)
      • 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
      • readOnly 属性:是否只读事务 ( true | false(默认值) )
      • propagation 属性:事务传播行为 ( SUPPORTS | REQUIRED(默认值) )
      • transactionManager 属性:多个事务管理器托管在 Spring 容器中时,指定事务管理器的 bean 名称
  • isolation 属性:设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况

    通常使用数据库的默认隔离级别即可,基本不需要进行设置

  • noRollbackFor 属性:设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚

标注位置说明:

  • 标注在类上:该类中所有方法都具有相同的事务配置
  • 标注在方法上:该方法具有事务配置
  • 同时标注在类上和方法上:就近原则(方法上的事务配置生效)
import cn.test.dao.AccountDao;
import cn.test.domain.Account;
import cn.test.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(propagation = Propagation.SUPPORTS)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    @Transactional
    //@Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public void transfer(String sourceName, String targetName, float money) throws Exception {
        //1、根据账户名称查询两个账户
        Account sourceAccount = accountDao.findByName(sourceName); //转出账户
        Account targetAccount = accountDao.findByName(targetName); //转入账户
        //2、操作金额转换(转出账户扣除金额,转入账户添加金额)
        sourceAccount.setMoney(sourceAccount.getMoney() - money);
        targetAccount.setMoney(targetAccount.getMoney() + money);
        //3、更新账户
        accountDao.update(sourceAccount);
        int i=1/0;
        accountDao.update(targetAccount);
    }
}


拓展

Spring 整合单元测试

当在单元测试中,点击 run 的时候,底层工作的其实是一个运行器,默认是 junit 提供的 ParentRunner 运行器,它是不认识Spring的环境,这也就意味着,它无法从 Spring 的容器中获取bean。

如果想要从 Spring 的容器中获取对象,需要使用 Spring 提供的运行器。

  • 引入依赖

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--spring-junit 整合单元测试-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>
  • @RunWith 注解:设置单元测试的运行器,通过 value 属性指定单元测试运行环境

    • JUnit4.class :指定使用 JUnit4 来运行
    • SpringJUnit4ClassRunner.class :Spring 测试环境
    • SpringRunner.class:Spring 测试环境

    注:

    • SpringRunner extends SpringJUnit4ClassRunner.class
    • 使用上 JUnit4.12 或更高版本以上 SpringRunner,SpringJUnit4ClassRunner 都可以使用

      但是推荐使用 SpringRunner,final类型,安全

    • JUnit4.12 以下版本就只能使用 SpringJUnit4ClassRunner
  • @ContextConfiguration 注解:指定容器的配置信息

    • localtions 属性:配置文件路径
    • classes 属性:配置类
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountJunitTest {

    @Autowired
    private AccountService accountService;

    //测试保存
    @Test
    public void testInsert() {
        //3、调用方法保存
        Account account = new Account();
        account.setMoney(100f);
        account.setName("小李1");
        accountService.saveAccount(account);
    }
}


配置文件的模块化

若配置都集中配在了一个applicationContext.xml文件中,当开发人员过多时, 如果所有bean都配置到同一个配置文件中,会使这个文件巨大,而且也不方便维护。针对这个问题,Spring提供了多配置文件的方式,也就是所谓的配置文件模块化。

  1. 并列的多个配置文件
    直接编写多个配置文件,比如说beans1.xml,beans2.xml......, 然后在创建ApplicationContext的时候,直接
    传入多个配置文件。

    ApplicationContext act = new ClassPathXmlApplicationContext("beans1.xml","beans2.xml","...");
  2. 主从配置文件
    先陪一个主配置文件,然后在里面导入其它的配置文件。

      <import resource="beans1.xml" />
      <import resource="beans2.xml" />
    
      <!--拓展:引入本地properties配置文件-->
      <context:property-placeholder location="classpath:db.properties"/>

注意事项:

  • 同一个xml文件中不能出现相同名称的bean,如果出现会报错
  • 多个xml文件如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载的bean,所以企业开发中尽
    量保证bean的名称是唯一的。


Spring Bean 单例的高并发安全问题

Spring的bean默认都是单例的,某些情况下,单例是并发不安全的,以Controller举例,问题根源在于,若在Controller中定义成员变量,多个请求来临,进入的都是同一个单例的Controller对象,若对此成员变量的值进行修改操作,则会互相影响,无法达到并发安全(不同于线程隔离的概念)的效果。

抛出问题

多次访问此url,可以看到每次的结果都是自增的,所以这样的代码显然是并发不安全的。

@Controller
public class HomeController {
    private int i;
    @GetMapping("testsingleton1")
    @ResponseBody
    public int test1() {
        return ++i;
    }
}

解决方案

方案1:尽量避免使用成员变量

在业务允许的条件下,尽量避免使用成员变量,使用方法中的局部变量


方案2:使用并发安全的类

Java作为功能性超强的编程语言,API丰富,如果非要在单例bean中使用成员变量,可以考虑使用并发安全的容器,如ConcurrentHashMap、ConcurrentHashSet等,将成员变量(一般可以是当前运行中的任务列表等这类变量)包装到这些并发安全的容器中进行管理即可。


方案3:分布式或微服务的并发安全

如果还要进一步考虑到微服务或分布式服务的影响,方案2便不足以处理了,所以可以借助于可以共享某些信息的分布式缓存中间件如Redis等,这样即可保证同一种服务的不同服务实例都拥有同一份共享信息(如当前运行中的任务列表等这类变量)。


方案4:单例变原型

对web项目,可以Controller类上加注解@Scope("prototype")或@Scope("request"),对非web项目,在Component类上添加注解@Scope("prototype")。

优点:实现简单

缺点:很大程度上增大了bean创建实例化销毁的服务器资源开销


不可用方案:线程隔离类ThreadLocal

web服务器默认的请求线程池大小为10,这10个核心线程可以被之后不同的Http请求复用。

ThreadLocal的方式可以达到线程隔离,但还是无法达到并发安全。


使用 @Autowired 注解给静态变量赋值

描述:

在一些工具类中可能会用到Ioc容器中的对象,而工具类中的成员变量往往是静态的,此时使用@Autowired注解就会出现NullpointerException(空指针异常)。

原理剖析:

静态变量、类变量不是对象的属性,而是一个类的属性,所以静态方法是属于类(class)的,普通方法才是属于实体对象(也就是New出来的对象)的,spring注入是在容器中实例化对象,所以不能使用静态方法。

而使用静态变量、类变量扩大了静态方法的使用范围。静态方法在spring是不推荐使用的,依赖注入的主要目的,是让容器去产生一个对象的实例,然后在整个生命周期中使用他们,同时也让testing工作更加容易。

一旦使用静态方法,就不再需要去产生这个类的实例,这会让testing变得更加困难,同时也不能为一个给定的类,依靠注入方式去产生多个具有不同的依赖环境的实例,这种static field是隐含共享的,并且是一种global全局状态,spring同样不推荐这样去做。


解决方案1:将@Autowire注解加到set方法上

@Component
public class Test {
    
    private static SessionFactory sessionFactory;
    
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        Test.sessionFactory = sessionFactory;
    }
}

解决方案2:用@PostConstruct注解

@Component
public class Test {
    
    private static SessionFactory sessionFactory;
    
    @Autowired
    private SessionFactory sessionFactory2;
    
    @PostConstruct
    public void beforeInit() {
        SessionFactory = sessionFactory2;
    }
}

解决方案3:将@Autowire注解加到构造方法上

@Component
public class Test {
    
    private static SessionFactory sessionFactory;
    
    @Autowired
    public Test(SessionFactory sessionFactory) {
        Test.SessionFactory = SessionFactory;
    }
}


非容器中的类调用容器中的类

描述:

使用@Autowired注入对象时,一般被注入的类都带有@Coponent、@Controller、@Service 、@repository等注解才可以。注入类和被注入类都被spring所管理,可以完成调用。但是当非容器类(没加以上注解时)使用@Autowired调用容器中的类时,注入对象为空,报空指针异常。

解决方案:

创建工具类BeanUtils,在这个工具类中的getBean可以得到容器中的类,在非容器类中使用

@Component
public class BeanUtils implements ApplicationContextAware {
    /**
     * 以静态变量保存ApplicationContext,可在任意代码中取出ApplicaitonContext.
     */
    private static ApplicationContext context;

    /**
     * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
     */
    @Override
    public void setApplicationContext(ApplicationContext context) {
        BeanUtils.context = context;
    }

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.  方法返回值的类型由调用者决定
     */
    public static <T> T getBean(String name) {
        return (T) context.getBean(name);
    }

    /// 获取当前环境
    public String getActiveProfile() {
        return context.getEnvironment().getActiveProfiles()[0];
    }
}

非容器类中使用容器中的类

public class StationFactory {
    Map<String, StationOperation> map = new HashMap<>();
    {
        map.put("定损中心主管指标表", BeanUtils.getBean("leadDSZXOperation"));
        map.put("定损中心员工指标表", BeanUtils.getBean("empDSZXOperation"));
        map.put("视频查勘中心主管指标表", BeanUtils.getBean("leadVideoSurveyCenterOperation"));
        map.put("视频查勘中心员工指标表", BeanUtils.getBean("empVideoSurveyCenterOperation"));
        map.put("视频定损中心主管指标表", BeanUtils.getBean("leadVideoDSCenterOperation"));
    }
}
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2天前
|
Java 数据安全/隐私保护 Spring
Java 中 Spring Boot 框架下的 Email 开发
Java 中 Spring Boot 框架下的 Email 开发
27 2
|
2天前
|
缓存 前端开发 Java
【框架】Spring 框架重点解析
【框架】Spring 框架重点解析
17 0
|
2天前
|
前端开发 Java 开发者
【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用
【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用
8 0
|
2天前
|
JSON 前端开发 Java
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解(下)
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解
6 0
|
2天前
|
Java
在高并发环境下,再次认识java 锁
在高并发环境下,再次认识java 锁
41 0
|
2天前
|
消息中间件 NoSQL Java
Java高级开发:高并发+分布式+高性能+Spring全家桶+性能优化
Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
|
2天前
|
存储 NoSQL Java
探索Java分布式锁:在高并发环境下的同步访问实现与优化
【4月更文挑战第17天】Java分布式锁是解决高并发下数据一致性问题的关键技术,通过Redis、ZooKeeper、数据库等方式实现。它确保多节点共享资源时的同步访问,防止数据不一致。优化策略包括锁超时重试、续期、公平性和性能优化。合理设计分布式锁对支撑大规模分布式系统至关重要。
|
2天前
|
缓存 负载均衡 Java
Java高并发性能指标
Java高并发是指在Java编程环境中,系统能够同时处理大量并发请求或操作的能力。这里的“高”强调的是并发处理的数量级较大,需要系统能够有效地管理多个并发的执行单元,如线程或进程,以确保它们能够高效且正确地执行。
14 0
|
2天前
|
JavaScript Java 测试技术
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
27 2
|
2天前
|
Java Go C语言
高并发时代到底是Go还是Java?
作为一名用过Java和Go开发过微服务架构程序的在校学生的角度思考,本文将从以下几个方便来讲述Go和Java的区别。