Java基于JNDI 实现读写分离的示例代码

目录
  • 一、JNDI数据源配置
  • 二、JNDI数据源使用
  • 三、web.xml配置
  • 四、spring-servlet.xml配置
  • 五、spring-db.xml配置
  • 六、log4j.properties配置
  • 七、相关路由数据源切换逻辑代码
  • 八、搭建过程中遇到的问题和解决方案

一、JNDI数据源配置

在Tomcat的conf目录下,context.xml在其中标签中添加如下JNDI配置:

<Resource name="dataSourceMaster" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
 auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWaitMillis="30000"
 username="root" password="root" driverClassName="com.mysql.jdbc.Driver"  url="jdbc:mysql://localhost:3306/user_master?useUnicode=true&amp;characterEncoding=utf-8"/>
<Resource name="dataSourceSlave" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
 auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWaitMillis="30000"
 username="root" password="root" driverClassName="com.mysql.jdbc.Driver"  url="jdbc:mysql://localhost:3306/user_slave?useUnicode=true&amp;characterEncoding=utf-8"/>

二、JNDI数据源使用

1、在普通web项目中

(1)在web.xml文件中添加如下配置(也可以不配置):

<resource-ref>
 <res-ref-name>dataSourceMaster</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
 <res-ref-name>dataSourceSlave</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>

三、web.xml配置

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>classpath:log4j.properties</param-value>
 </context-param>
 <context-param>
  <param-name>log4jRefreshInterval</param-name>
  <param-value>60000</param-value>
 </context-param>
 <filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>utf-8</param-value>
  </init-param>
  <init-param>
   <param-name>forceEncoding</param-name>
   <param-value>true</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <servlet-name>xiyun</servlet-name>
 </filter-mapping>
 <servlet>
  <servlet-name>xiyun</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>        classpath:conf/spring/spring-servlet.xml      </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>xiyun</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
</web-app>

四、spring-servlet.xml配置

<?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:mvc="http://www.springframework.org/schema/mvc"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">    

 <context:component-scan base-package="com.xiaoxi"/>    

 <mvc:annotation-driven/>    

 <import resource="classpath:conf/spring/spring-db.xml"/>    

 <bean id="viewResolver"          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/freemarker/"/>
  <property name="suffix" value=".ftl"/>
  </bean>
 </beans>

五、spring-db.xml配置

<?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:aop="http://www.springframework.org/schema/aop"       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
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >    

 <!-- 主数据源配置 -->
 <bean id="dataSourceMaster" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="java:comp/env/dataSourceMaster"/>
 </bean>
 <!-- 从数据源配置 -->
 <bean id="dataSourceSlave" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="java:comp/env/dataSourceSlave"/>
 </bean>    

 <aop:aspectj-autoproxy proxy-target-class="true"/>    

    <context:annotation-config/>    

 <bean id="dynamicDataSource" class="com.xiaoxi.config.DynamicRoutingDataSource">
  <property name="targetDataSources">
   <map>
    <entry key="Master" value-ref="dataSourceMaster"/>
    <entry key="Slave" value-ref="dataSourceSlave"/>
   </map>
  </property>
  <property name="defaultTargetDataSource" value="dataSourceMaster"/>
 </bean>    

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <!-- 配置数据源 -->
  <property name="dataSource" ref="dynamicDataSource"/>
 </bean>    

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <!-- 映射数据源 -->
  <property name="dataSource" ref="dynamicDataSource"/>
  <!-- 映射mybatis核心配置文件 -->
  <property name="configLocation" value="classpath:conf/spring/mybatis-config.xml"/>
  <!-- 映射mapper文件 -->
  <property name="mapperLocations">
   <list>
    <value>classpath:conf/sqlMap/*.xml</value>
   </list>
  </property>
 </bean>    

 <!-- 获得sqlSession -->
 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
 </bean>    

 <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <!-- 这里的basePackage 指定了dao层接口路劲,这里的dao接口不用自己实现 -->
  <property name="basePackage" value="com.xiaoxi.dao" />
  <!-- 如果只有一个数据源的话可以不用指定,但是如果有多个数据源的话必须要指定 -->
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
  <!--直接指定了sqlsessionTemplate名称,这个和上面的其实是一样的 -->
  <property name="sqlSessionTemplateBeanName" value="sqlSession" />
 </bean>
</beans>

六、log4j.properties配置

log4j.rootLogger=DEBUG, CATALINA# Define all the appenders
log4j.appender.CATALINA=org.apache.log4j.RollingFileAppender
log4j.appender.CATALINA.File=${catalina.base}/logs/catalina.log
log4j.appender.CATALINA.Append=true
log4j.appender.CATALINA.MaxFileSize=10MB
log4j.appender.CATALINA.Encoding=UTF-8

# Roll-over the log once per day
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.LOCALHOST=org.apache.log4j.RollingFileAppender
log4j.appender.LOCALHOST.File=${catalina.base}/logs/localhost.log
log4j.appender.LOCALHOST.MaxFileSize=10MB
log4j.appender.LOCALHOST.Append=true
log4j.appender.LOCALHOST.Encoding=UTF-8
log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout
log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.MANAGER=org.apache.log4j.RollingFileAppender
log4j.appender.MANAGER.File=${catalina.base}/logs/manager.log
log4j.appender.MANAGER.MaxFileSize=10MB
log4j.appender.MANAGER.Append=true
log4j.appender.MANAGER.Encoding=UTF-8
log4j.appender.MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.HOST-MANAGER=org.apache.log4j.RollingFileAppender
log4j.appender.HOST-MANAGER.File=${catalina.base}/logs/host-manager.log
log4j.appender.HOST-MANAGER.MaxFileSize=10MB
log4j.appender.HOST-MANAGER.Append=true
log4j.appender.HOST-MANAGER.Encoding=UTF-8
log4j.appender.HOST-MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

# Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]= INFO, MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]= INFO, HOST-MANAGER

七、相关路由数据源切换逻辑代码

package com.xiaoxi.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;

public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDbType();
    }
}
package com.xiaoxi.config;

/**
 * 线程上下文 <br>
 * 用于保存线程本地变量DbType(用于切换数据源)
 * 如果是异步线程操作,需要用InheritableThreadLocal (需要保存父线程的变量)
 *
 * @see [相关类/方法](可选)
 * @since [产品/模块版本](可选)
 */
public class DataSourceContextHolder {

    private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>();

    public static ThreadLocal<DbType> getLocal() {
        return contextHolder;
    }

    private DataSourceContextHolder () {}

    public static String getDbType() {
        return contextHolder.get() == null ? DbType.MASTER.dbType : contextHolder.get().dbType;
    }

    public static void setDbType(DbType dbType) {
        contextHolder.set(dbType);
    }

    public static void clearDbType() {
        contextHolder.remove();
    }

    public enum DbType {

        MASTER("Master"),

        SLAVE("Slave");

        private String dbType;

        DbType(String dbType) {
            this.dbType = dbType;
        }

        public String getDbType() {
            return dbType;
        }
    }
}
package com.xiaoxi.aop;

import com.xiaoxi.config.DataSourceContextHolder;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 数据源切面,用于在执行sql前进行读写数据源切换 <br>
 * 〈功能详细描述〉
 *
 * @see [相关类/方法](可选)
 * @since [产品/模块版本](可选)
 */
@Aspect
@Order(-1)
@Component
public class DataSourceAop {

    private static Logger logger = Logger.getLogger(DataSourceAop.class);

    @Before("execution(* com.xiaoxi.dao..*.query*(..))")
    public void setReadDataSourceType() {
        DataSourceContextHolder.setDbType(DataSourceContextHolder.DbType.MASTER);
        logger.debug("[DataSourceAop] DataSource Covert To SLAVE");
    }

    @Before("execution(* com.xiaoxi.dao..*.insert*(..))" +
         "|| execution(* com.xiaoxi.dao..*.update*(..))" +
         "|| execution(* com.xiaoxi.dao..*.delete*(..))")
    public void setWriteDataSourceType() {
        DataSourceContextHolder.setDbType(DataSourceContextHolder.DbType.SLAVE);
        logger.debug("[DataSourceAop] DataSource Covert To MASTER");
    }

    /** ☆☆☆☆☆ 也可以获取参数中路由字段进行切换数据源 ☆☆☆☆☆ **/

    @Pointcut("execution(* com.xiaoxi.dao..*.*(..))")
    public void cutPoint() {}

    @Before(value="cutPoint()")
    public void setDynamicDataSource(JoinPoint point){
        String className = point.getTarget().getClass().getSimpleName();
        String methodName = point.getSignature().getName();
        String log = "[DataSourceAop] className:%s, methodName:%s";
        logger.debug(String.format(log, className, methodName));
    }
}

八、搭建过程中遇到的问题和解决方案

1、注入数据源dataSourceMaster和dataSourceSlave失败
spring 中jndiName配置的数据源名称和Tomcat配置文件中Resource name存在区别,并非一致,其中java:comp/env为环境,否则会报can not find jndi name …

2、Cannot create JDBC driver of class ‘' for connect URL ‘null'

3、The requested resource is not available(404)
分析了web.xml和servlet.xml发现配置无误,注解驱动和包扫描都配置,但仍然访问不了,后发现
项目启动过程中打印的日志存在问题,如下:
2019-12-17 16:20:41,767 [RMI TCP Connection(3)-127.0.0.1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping- Mapped “{[/userInfo],methods=[GET]}” onto public java.lang.String com.xiaoxi.controller.UserInfoController.queryUserInfoById(java.lang.String)
通过分析发现这里的请求映射,通过controller的requestMapping映射到具体方法,却丢失了方法上的requestMapping路径,后发现方法RequestMapping写法如下:

@Controller
@RequestMapping("/userInfo")
public class UserInfoController {

    private static Logger logger =Logger.getLogger(UserInfoController.class);

    @Autowired
    private UserInfoService userInfoService;

    @ResponseBody
    @RequestMapping(name= "/queryUserInfoById", method = RequestMethod.GET)
    public String queryUserInfoById(@RequestParam("id") String id){
        logger.info("UserInfoController.queryUserInfoById.  id:{}" + id);
        UserInfo userInfo = userInfoService.queryUserInfoById(id);
        return JSON.toJSONString(userInfo);
    }
}

此处的RequestMapping属性name应该改为value,否则解析为空(可查看注解定义)

到此这篇关于Java基于JNDI 实现读写分离的示例代码的文章就介绍到这了,更多相关Java JNDI读写分离内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java之JNDI注入的实现

    目录 About JNDI 0x01 简介 0x02 JNDI的用途 0x03 日常使用 0x04 JNDI命名和目录服务 前置知识 InitialContext类 Reference类 JNDI Demo JNDI+RMI攻击手法 JNDI+LDAP攻击手法 Reference About JNDI 0x01 简介 JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提

  • JNDI在JavaEE中的角色_动力节点Java学院整理

    虽然 J2EE 平台提高了普通企业开发人员的生活水平,但是这种提高是以不得不学习许多规范和技术为代价的,这些规范和技术则是 J2EE 为了成为无所不包的分布式计算平台而整合进来的.Dolly Developer 是众多开发人员中的一员,她已经发现了一个特性,该特性有助于缓解随企业级应用程序部署而带来的负担,这个特性就是 JNDI,即 Java 命名与目录接口(Java Naming and Directory Interface).让我们来看看 Dolly 在没有 JNDI 的时候是怎么做的,以

  • JNDI简介_动力节点Java学院整理

    一.JNDI是什么? JNDI--Java 命名和目录接口(Java Naming and Directory Interface),是一组在Java应用中访问命名和目录服务的API. 二.JNDI好处 解耦:通过注册.查找JNDI服务,可以直接使用服务,而无需关心服务提供者,这样程序不至于与访问的资源耦合! JNDI优点  包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务: 可以同时连接到多个命名或目录服务上: 建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必知道对象

  • Java JNDI案例详解

    JNDI的理解 JNDI是 Java 命名与文件夹接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之中的一个,不少专家觉得,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识.  那么,JNDI究竟起什么作用?//带着问题看文章是最有效的  要了解JNDI的作用,我们能够从"假设不用JNDI我们如何做?用了JNDI后我们又将如何做?"这个问题来探讨.  没有JNDI的做法:  程序猿开发时,知道要开发訪

  • Java中的命名与目录接口JNDI基本操作方法概览

    对jndi总体的理解: jndi(java naming and directory Interface)它提供了一套使用命名和目录服务的接口.用户可以通过它来使用命名和目录服务.就像jdbc一样.jndi包括命名服务和目录服务两部分,其中目录服务包含目录对象directory object,它包含若干属性对象.提供了对属性的很多操作. 命名和目录服务: 命名和目录服务我们一直在使用,如操作系统的文件系统,它给我们提供对文件的操作,查询,添加删除等功能.DNS服务将url同ip地址绑定在了一起.

  • Java使用JNDI连接数据库的实现方法

    目录 项目背景 环境 概念 数据源与连接池 什么是JNDI JNDI优点 JDNI在Tomcat中的配置 Jar包 测试准备 JNDI配置 全局引用 局部引用 参考资料 项目背景 在项目中本身使用的SQL Server 数据库,某些功能下需要访问Sybase数据库(都淘汰的东西 QAQ),考虑到功能较少并且我们的UAT和PROD环境使用的是WebSphere,其本身已经存在JNDI的连接方式,因此我决定使用JNDI设置,那么就需要解决JNDI在Tomcat下的配置了,找了很多资料,说到这,不得不

  • Java基于JNDI 实现读写分离的示例代码

    目录 一.JNDI数据源配置 二.JNDI数据源使用 三.web.xml配置 四.spring-servlet.xml配置 五.spring-db.xml配置 六.log4j.properties配置 七.相关路由数据源切换逻辑代码 八.搭建过程中遇到的问题和解决方案 一.JNDI数据源配置 在Tomcat的conf目录下,context.xml在其中标签中添加如下JNDI配置: <Resource name="dataSourceMaster" factory="or

  • java使用spring实现读写分离的示例代码

    最近上线的项目中数据库数据已经临近饱和,最大的一张表数据已经接近3000W,百万数据的表也有几张,项目要求读数据(select)时间不能超过0.05秒,但实际情况已经不符合要求,explain建立索引,使用redis,ehcache缓存技术也已经满足不了要求,所以开始使用读写分离技术,可能以后数据量上亿或者更多的时候,需要再去考虑分布式数据库的部署,但目前来看,读写分离+缓存+索引+表分区+sql优化+负载均衡是可以满足亿级数据量的查询工作的,现在就一起来看一下亲测可用的使用spring实现读写

  • SpringBoot+MyBatis+AOP实现读写分离的示例代码

    目录 一. MySQL 读写分离 1.1.如何实现 MySQL 的读写分离? 1.2.MySQL 主从复制原理? 1.3.MySQL 主从同步延时问题(精华) 二.SpringBoot+AOP+MyBatis实现MySQL读写分离 2.1.AbstractRoutingDataSource 2.2.如何切换数据源 2.3.如何选择数据源 三 .代码实现 3.0.工程目录结构 3.1.引入Maven依赖 3.2.编写配置文件,配置主从数据源 3.3.Enum类,定义主库从库 3.4.ThreadL

  • Java基于IDEA实现http编程的示例代码

    http开发前言之为什么要有应用层 我们已经学过TCP/IP , 已经知道目前数据能从客户端进程经过路径选择跨网络传送到服务器端进程 [ IP+Port ],可是,仅仅把数据从A点传送到B点就完了吗?这就好比,在淘宝上买了一部手机,卖家[ 客户端 ]把手机通过顺丰[ 传送+路径选择 ] 送到买家 [ 服务器 ] 手里就完了吗?当然不是,买家还要使用这款产品,还要在使用之后,给卖家打分评论.所以,我们把数据从A端传送到B端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,

  • java基于mongodb实现分布式锁的示例代码

    目录 原理 实现 使用 原理 通过线程安全findAndModify 实现锁 实现 定义锁存储对象: /** * mongodb 分布式锁 */ @Data @NoArgsConstructor @AllArgsConstructor @Document(collection = "distributed-lock-doc") public class LockDocument { @Id private String id; private long expireAt; privat

  • Java基于LoadingCache实现本地缓存的示例代码

    目录 一. 添加 maven 依赖 二.CacheBuilder 方法说明 三.创建 CacheLoader 四.工具类 五.guava Cache数据移除 一. 添加 maven 依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</version> </depend

  • Sharding-JDBC自动实现MySQL读写分离的示例代码

    目录 一.ShardingSphere和Sharding-JDBC概述 1.1.ShardingSphere简介 1.2.Sharding-JDBC简介 1.3.Sharding-JDBC作用 1.4.ShardingSphere规划线路图 1.5.ShardingSphere三种产品的区别 二.数据库中间件 2.1.数据库中间件简介 2.2.Sharding-JDBC和MyCat区别 三.Sharding-JDBC+MyBatisPlus实现读写分离 3.0.项目代码结构和建表SQL语句 3.

  • java基于jedisLock—redis分布式锁实现示例代码

    分布式锁是啥? 单机锁的概念:我们正常跑的单机项目(也就是在tomcat下跑一个项目不配置集群)想要在高并发的时候加锁很容易就可以搞定,java提供了很多的机制例如:synchronized.volatile.ReentrantLock等锁的机制. 为啥需要分布式锁:当我们的项目比较庞大的时候,单机版的项目已经不能满足吞吐量的需求了,需要对项目做负载均衡,有可能还需要对项目进行解耦拆分成不同的服务,那么肯定是做成分布式的项目,分布式的项目因为是不同的程序控制,所以使用java提供的锁并不能完全保

  • SpringBoot整合sharding-jdbc实现分库分表与读写分离的示例

    目录 一.前言 二.数据库表准备 三.整合 四.docker-compose部署mysql主从 五.本文案例demo源码 一.前言 本文将基于以下环境整合sharding-jdbc实现分库分表与读写分离 springboot2.4.0 mybatis-plus3.4.3.1 mysql5.7主从 https://github.com/apache/shardingsphere 二.数据库表准备 温馨小提示:此sql执行时,如果之前有存在相应库和表会进行自动删除后再创建! DROP DATABAS

  • Java多线程之readwritelock读写分离的实现代码

    在多线程开发中,经常会出现一种情况,我们希望读写分离.就是对于读取这个动作来说,可以同时有多个线程同时去读取这个资源,但是对于写这个动作来说,只能同时有一个线程来操作,而且同时,当有一个写线程在操作这个资源的时候,其他的读线程是不能来操作这个资源的,这样就极大的发挥了多线程的特点,能很好的将多线程的能力发挥出来. 在Java中,ReadWriteLock这个接口就为我们实现了这个需求,通过他的实现类ReentrantReadWriteLock我们可以很简单的来实现刚才的效果,下面我们使用一个例子

随机推荐