spring boot redis 分布式锁

 

yml文件

  redis:host: 127.0.0.1port: 40197password: 123456timeout: 5000database: 0jedis:pool:min-idle: 0max-idle: 8max-active: 8max-wait: -1

 

RedisConfig.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import redis.clients.jedis.JedisPoolConfig;import java.io.Serializable;
import java.time.Duration;/*** @author  */
@Configuration
@ConditionalOnProperty("spring.redis.host")
@EnableCaching
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {@Value("${spring.redis.host}")String redisHost;@Value("${spring.redis.port}")int redisPort;@Value("${spring.redis.password}")String redisPassword;@Value("${spring.redis.timeout}")int redisTimeout;@Value("${spring.redis.database}")int redisDatabase;@Value("${spring.redis.jedis.pool.min-idle}")int jedisMinIdle;@Value("${spring.redis.jedis.pool.max-idle}")int jedisMaxIdle;@Value("${spring.redis.jedis.pool.max-active}")int jedisMaxActive;@Value("${spring.redis.jedis.pool.max-wait}")int jedisMaxWait;/*** 自定义缓存key生成策略* @return KeyGenerator*/@Bean@Overridepublic KeyGenerator keyGenerator() {return (target, method, params) -> {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();};}@Beanpublic RedisConnectionFactory connectionFactory() {JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(jedisMaxActive);poolConfig.setMaxIdle(jedisMaxIdle);poolConfig.setMaxWaitMillis(jedisMaxWait);poolConfig.setMinIdle(jedisMinIdle);poolConfig.setTestOnBorrow(true);poolConfig.setTestOnReturn(false);poolConfig.setTestWhileIdle(true);JedisClientConfiguration clientConfig = JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig).and().readTimeout(Duration.ofMillis(redisTimeout)).build();// 单点redisRedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();log.debug(JSON.toJSONString(redisStandaloneConfiguration));redisStandaloneConfiguration.setHostName(redisHost);redisStandaloneConfiguration.setPassword(RedisPassword.of(redisPassword));redisStandaloneConfiguration.setPort(redisPort);redisStandaloneConfiguration.setDatabase(redisDatabase);return new JedisConnectionFactory(redisStandaloneConfiguration, clientConfig);}/*** 缓存管理器* @param redisConnectionFactory RedisConnectionFactory* @return CacheManager*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {// 设置缓存有效期一小时int hour = 1;RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(hour));return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();}@Beanpublic RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String, String> template = new RedisTemplate<>();template.setConnectionFactory(factory);//设置序列化工具setSerializer(template);template.afterPropertiesSet();return template;}private void setSerializer(RedisTemplate<String, String> template) {RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();RedisSerializer<Serializable> genericToStringSerializer = new GenericToStringSerializer<>(Serializable.class);log.debug(String.valueOf(genericToStringSerializer));RedisSerializer<Object> jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();log.debug(String.valueOf(jdkSerializationRedisSerializer));Jackson2JsonRedisSerializer<Serializable> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Serializable.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);RedisSerializer<Object> genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();RedisSerializer<Serializable> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Serializable.class);template.setEnableDefaultSerializer(true);template.setDefaultSerializer(fastJsonRedisSerializer);template.setStringSerializer(stringRedisSerializer);template.setKeySerializer(stringRedisSerializer);template.setValueSerializer(genericJackson2JsonRedisSerializer);template.setHashKeySerializer(stringRedisSerializer);template.setHashValueSerializer(fastJsonRedisSerializer);}}

 

 

应用Java


import com.alibaba.fastjson.JSON;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import com.chinamobile.scm.order.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public   class RedisServiceImpl<T extends Serializable> implements RedisService<T> {@Value("${spring.application.name}")String app;@AutowiredRedisTemplate<String, String> redisTemplate;@Overridepublic final String getApp() {return app;}@Overridepublic final RedisTemplate<String, String> getRedisTemplate() {return redisTemplate;}@Overridepublic   void set(String key, String value) {Assert.notNull(key, "参数id不能为空");log.debug("set key:" + key + ",value:" + value);redisTemplate.opsForValue().set(key, value);}@Overridepublic String get(String key) {Assert.notNull(key, "参数key不能为空");log.info("get id:" + key +" start get value");Object obv ="";try {obv = redisTemplate.opsForValue().get(key);}catch (Exception exp){String messageerr=exp.getMessage();if(messageerr.indexOf("loginUserId")>-1){int idxloginUserId=messageerr.indexOf("loginUserId");String loginstartidx=messageerr.substring(idxloginUserId-1);int idxsencond=loginstartidx.indexOf(",");String endindexstr=loginstartidx.substring(0,idxsencond);String valuestr="{"+endindexstr.replaceAll(",","")+"}";obv=valuestr;}}// Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\String vo=(String)obv;log.info("get id:" + key + ",value:" + vo);return  vo;}
public static void main(String[] args)
{String messageerr="Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\"; line: 1, column: 135]; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\"; line: 1, column: 135]";if(messageerr.indexOf("loginUserId")>-1){int idxloginUserId=messageerr.indexOf("loginUserId");String loginstartidx=messageerr.substring(idxloginUserId-1);int idxsencond=loginstartidx.indexOf(",");String endindexstr=loginstartidx.substring(0,idxsencond);String valuestr="{"+endindexstr.replaceAll(",","")+"}";System.out.println(valuestr);}}}

 

 

基础Service Redis类


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chinamobile.framework.common.constant.CommonConstant;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;@SuppressWarnings("unused")
public interface BaseRedisService {String getApp();RedisTemplate<String, String> getRedisTemplate();/*** 根据module和id生成redis的key* @param module 业务场景code* @param id 主键* @return key*/default String generateKey(BaseRedisEnum module, String id) {StringBuilder buffer = new StringBuilder();Assert.hasText(getApp(), "配置spring.application.name错误");Assert.notNull(module, "参数module错误");Assert.notNull(id, "参数id不能为空");Assert.isTrue(!id.startsWith("\"") && !id.endsWith("\""), "id不能以引号开始且不能以引号结束");buffer.append(getApp()).append(CommonConstant.COLON).append(module.getKey());if (!StringUtils.isEmpty(id)) {return buffer.append(CommonConstant.COLON).append(id).toString();}return "\"" + buffer.toString() + "\"";//必须加引号,超过32个字符}default Collection<String> generateKeys(BaseRedisEnum module, Collection<String> ids) {if (ids == null) {return null;}Collection<String> keys = new ArrayList<>();for (String id : ids) {keys.add(generateKey(module, id));}return keys;}/*** 删除缓存 根据key精确匹配删除* @param module 业务场景code* @param id 主键*/default void delete(BaseRedisEnum module, String id) {this.delete(module, new String[]{id});}/*** 删除缓存 根据keys批量精确匹配删除* @param module 业务场景code* @param ids 主键数组*/default void delete(BaseRedisEnum module, String[] ids) {if (ids != null && ids.length > 0) {List<String> delKeys = new ArrayList<>();for (String id : ids) {if (!StringUtils.hasText(id)) {delKeys.add(generateKey(module, id));}}getRedisTemplate().delete(delKeys);}}/*** 指定缓存的失效时间* @param module 业务场景code* @param id 主键* @param second 有效时间,单位秒* @return 是否成功*/default Boolean expire(BaseRedisEnum module, String id, long second) {return expire(module, id, second, TimeUnit.SECONDS);}default Boolean expire(BaseRedisEnum module, String id, long time, TimeUnit unit) {Assert.notNull(id, "参数id不能为空");String key = generateKey(module, id);if (time > 0) {return getRedisTemplate().expire(key, time, unit);}return Boolean.FALSE;}/*** 查看key是否存在* @param module 业务场景code* @param id 主键* @return redis的key集合*/default Set<String> keys(BaseRedisEnum module, String id) {StringBuilder pattern = new StringBuilder();Assert.hasText(getApp(), "配置spring.application.name错误");Assert.notNull(module, "参数module错误");pattern.append(getApp()).append(CommonConstant.COLON).append(module.getKey());if (!StringUtils.isEmpty(id)) {pattern.append(CommonConstant.COLON).append(id);}pattern.append("*");return getRedisTemplate().keys(pattern.toString());}/*** 检查key是否存在* @param module 业务场景code* @param id 主键* @return 是否存在,true存在,false不存在*/default boolean exist(BaseRedisEnum module, String id) {Assert.notNull(id, "参数id不能为空");String key = generateKey(module, id);Boolean bool = getRedisTemplate().hasKey(key);if (bool == null) {return false;}return bool;}default <T extends Serializable> Map<String, String> generateMap(BaseRedisEnum module, Map<String, T> data) {Map<String, String> map = new HashMap<>();for (Map.Entry<String, T> entry : data.entrySet()) {BaseRedisVo<T> vo = new BaseRedisVo<>(entry.getValue());map.put(generateKey(module, entry.getKey()), JSON.toJSONString(vo));}return map;}@SuppressWarnings("unchecked")@SneakyThrowsdefault <T> T transfer(String vo) {if (vo == null) {return  null;}JSONObject json = JSON.parseObject(vo);BaseRedisVo<JSONObject> v = json.toJavaObject(BaseRedisVo.class);Class<T> clazz = (Class<T>) Class.forName(v.getClazzT());JSONObject data = v.getData();return data.toJavaObject(clazz);}@SneakyThrowsdefault <T extends Serializable> List<T> transfer(List<String> list) {List<T> result = new ArrayList<>();if (CollectionUtils.isEmpty(list)) {return result;}for (String vo : list) {if (vo != null) {result.add(transfer(vo));}}return result;}@SneakyThrowsdefault <T extends Serializable> Set<T> transfer(Set<String> set) {Set<T> result = new HashSet<>();if (CollectionUtils.isEmpty(set)) {return result;}for (String vo : set) {if (vo != null) {result.add(transfer(vo));}}return result;}}

调用方分类


import com.alibaba.fastjson.JSON;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public final class RedisObjectServiceImpl<T extends Serializable> implements RedisObjectService<T> {@Value("${spring.application.name}")String app;@AutowiredRedisTemplate<String, String> redisTemplate;@Overridepublic final String getApp() {return app;}@Overridepublic final RedisTemplate<String, String> getRedisTemplate() {return redisTemplate;}@Overridepublic final void set(BaseRedisEnum module, String id, T value) {Assert.notNull(id, "参数id不能为空");BaseRedisVo<T> vo = new BaseRedisVo<>(value);String v = JSON.toJSONString(vo);log.debug("set id:" + id + ",value:" + v);redisTemplate.opsForValue().set(generateKey(module, id), v);}@Overridepublic final void set(BaseRedisEnum module, String id, T value, long second) {Assert.notNull(id, "参数id不能为空");BaseRedisVo<T> vo = new BaseRedisVo<>(value);String key = generateKey(module, id);redisTemplate.opsForValue().set(key, JSON.toJSONString(vo), second, TimeUnit.SECONDS);}@Overridepublic final Boolean setIfAbsent(BaseRedisEnum module, String id, T value) {Assert.notNull(id, "参数id不能为空");BaseRedisVo<T> vo = new BaseRedisVo<>(value);return redisTemplate.opsForValue().setIfAbsent(generateKey(module, id), JSON.toJSONString(vo));}@Overridepublic final void multiSet(BaseRedisEnum module, Map<String, T> data) {Assert.notEmpty(data, "参数data不能为空");redisTemplate.opsForValue().multiSet(generateMap(module, data));}@Overridepublic final Boolean multiSetIfAbsent(BaseRedisEnum module, Map<String, T> data) {Assert.notEmpty(data, "参数data不能为空");return redisTemplate.opsForValue().multiSetIfAbsent(generateMap(module, data));}@Overridepublic final T get(BaseRedisEnum module, String id) {Assert.notNull(id, "参数id不能为空");String vo = redisTemplate.opsForValue().get(generateKey(module, id));log.debug("get id:" + id + ",value:" + vo);return transfer(vo);}@Overridepublic final T getAndSet(BaseRedisEnum module, String id, T value) {Assert.notNull(id, "参数id不能为空");BaseRedisVo<T> v = new BaseRedisVo<>(value);String vo = redisTemplate.opsForValue().getAndSet(generateKey(module, id), JSON.toJSONString(v));return transfer(vo);}@Overridepublic final List<T> multiGet(BaseRedisEnum module, Collection<String> ids) {Assert.notEmpty(ids, "参数ids不能为空");List<String> list = redisTemplate.opsForValue().multiGet(generateKeys(module, ids));return transfer(list);}@Overridepublic final long generate(BaseRedisEnum module, String id) {Assert.notNull(id, "参数id不能为空");return generate(module, id, 1);}@Overridepublic final long generate(BaseRedisEnum module, String id, Date expireTime) {Assert.notNull(id, "参数id不能为空");return generate(module, id, 1, expireTime);}@Overridepublic final long generate(BaseRedisEnum module, String id, int increment) {Assert.notNull(id, "参数id不能为空");RedisAtomicLong counter = new RedisAtomicLong(generateKey(module, id), Objects.requireNonNull(redisTemplate.getConnectionFactory()));return counter.addAndGet(increment);}@Overridepublic final long generate(BaseRedisEnum module, String id, int increment, Date expireTime) {Assert.notNull(id, "参数id不能为空");RedisAtomicLong counter = new RedisAtomicLong(generateKey(module, id), Objects.requireNonNull(redisTemplate.getConnectionFactory()));counter.expireAt(expireTime);return counter.addAndGet(increment);}}

 

分布式锁


import com.chinamobile.framework.common.constant.CommonConstant;
import com.chinamobile.framework.common.exception.CommonException;
import com.chinamobile.framework.redis.enums.CommonDistributedLockEnum;
import com.chinamobile.framework.redis.service.CommonDistributedLockService;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.utils.ProjectUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public class CommonDistributedLockServiceImpl implements CommonDistributedLockService {private static final long DEFAULT_EXPIRE = -1;@Resourceprivate ApplicationContext applicationContext;@Resourceprivate RedisObjectService<String> redisObjectService;@Overridepublic boolean lock(String id) {log.debug("lock:id=" + id);return this.lock(id, DEFAULT_EXPIRE);}@SneakyThrows@Overridepublic boolean lock(String id, long second) {log.debug("lock:id=" + id + ",time(s)=" + second);if (!isValidLock(id)) {throw new CommonException(CommonConstant.TOO_FREQUENT_CODE, "操作太频繁,请稍候再试。");}String ip = ProjectUtil.getIp(applicationContext.getEnvironment());String port = ProjectUtil.getPort(applicationContext.getEnvironment());String value = ip + "_" + port;if (!redisObjectService.setIfAbsent(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, value)) {throw new CommonException(CommonConstant.TOO_FREQUENT_CODE, "操作太频繁,请稍候再试。");}if (second > 0) {return redisObjectService.expire(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, second);}return true;}@Overridepublic void unlock(String id) {log.debug("unlock:id=" + id);
//		redisObjectService.delete(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id);redisObjectService.expire(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, 1, TimeUnit.NANOSECONDS);//改成1毫秒过期}@SneakyThrows@Overridepublic void cleanLock() {List<String> deletes = new ArrayList<>();Set<String> keys = redisObjectService.keys(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, null);if (!CollectionUtils.isEmpty(keys)) {String ip = ProjectUtil.getIp(applicationContext.getEnvironment());String port = ProjectUtil.getPort(applicationContext.getEnvironment());String data = ip + "_" + port;for (String key : keys) {String vo = redisObjectService.getRedisTemplate().opsForValue().get(key);if (vo != null && data.equals(redisObjectService.transfer(vo))) {deletes.add(key);redisObjectService.getRedisTemplate().expire(key, 1, TimeUnit.NANOSECONDS);}}log.info("cleanLock:ids=" + deletes);
//			redisObjectService.getRedisTemplate().delete(deletes);}}@Overridepublic boolean isValidLock(String id) {log.debug("isValidLock:id=" + id);return !redisObjectService.exist(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id);}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql函数(二.数字函数)

数字函数 1.ROUND(X) 四舍五入取整数 ROUND(X,D) 四舍五入根据D几&#xff0c;来保留几位小数 (1)四舍五入取整数 select ROUND(1.567); 结果&#xff1a;2 (2)四舍五入根据D2&#xff0c;来保留2位小数 select ROUND(1.567&#xff0c;2)DESC; 结果&#xff1a;1.57 2.CEIL…

这份1307页Android面试全套真题解析,源码+原理+手写框架

前言 前不久&#xff0c;几个朋友聚会&#xff0c;谈到了现在的后辈&#xff0c;我就说起了那个大三就已经拿到网易offer的小学弟。 这个学弟是00后&#xff0c;专升本进入我们学校的。进来后就非常努力&#xff0c;每次上课都是第一个到教室的&#xff0c;每次都是坐第一排&…

CAS的ABA问题描述 AtomicStampReference

CAS的ABA问题描述 在CAS操作的时候&#xff0c;其他线程将当前变量的值从A改成B&#xff0c;又改回A&#xff1b;CAS线程用期望值A与当前变量比较的时候&#xff0c;发现当前变量没有变&#xff0c;于是CAS就将当前变量进行了交换操作&#xff0c;但其实当前变量改变过&#x…

[转]OpenContrail 体系架构文档

OpenContrail 体系架构文档英文原文&#xff1a;http://opencontrail.org/opencontrail-architecture-documentation/ 翻译者&#xff1a;KkBLuE知行合一 其微信号&#xff1a;kkbluepublic&#xff0c; SDNAP.com翻译整理 OpenContrail 体系架构文档 1 概述 1.1 使用案例 1…

这份354页笔记的Android进阶知识+大厂高频面试题,绝对干货

程序员与别的专业有所不同&#xff0c;其他专业都是越老越香&#xff0c;而程序员却是一个例外&#xff0c;因为计算机技术更新太快&#xff0c;而且工作强度很大&#xff0c;因此大部分程序员只会写 3 年代码。3 年后要不晋升做项目经理&#xff0c;要么转行&#xff0c;个别研…

原子性 atomic 类用法

当程序更新一个变量时&#xff0c;如果多线程同时更新这个变量&#xff0c;可能得到期望之外的值&#xff0c;比如变量i1&#xff0c;A线程更新i1&#xff0c;B线程也更新i1&#xff0c;经过两个线程操作之后可能i不等于3&#xff0c;而是等于2。因为A和B线程在更新变量i的时候…

这是一份用心整理的Android面试总结,聪明人已经收藏了!

前言 本文想分享的是如何准备阿里面试的以及面试过程的所想所得&#xff0c;希望能帮到你。 首先&#xff0c;可能要让你们失望的是&#xff0c;这篇文章不会有大篇幅的面试题答案。如果想要看这方面的内容&#xff0c;可以看我之前的文章。感谢关注 很多人准备面试的时候&a…

git 技能图

---- 转载于:https://www.cnblogs.com/WHWWHW/p/11136606.html

AtomicStampedReference源码分析

之前的文章已经介绍过CAS的操作原理&#xff0c;它虽然能够保证数据的原子性&#xff0c;但还是会有一个ABA的问题。 那么什么是ABA的问题呢&#xff1f;假设有一个共享变量“num”,有个线程A在第一次进行修改的时候把num的值修改成了33。修改成功之后&#xff0c;紧接着又立刻…

django:bootstrap table加载django返回的数据

bootstrap table加载表格数据有两类方式&#xff1a; 一种通过data属性的方式配置&#xff0c;一种是javascipt方式配置 这里看js配置方式&#xff1a; 1、当数据源为.json文件时 url参数写上json文件的地址就行&#xff0c;但是json文件格式必须为json格式(2种): a:一种为json…

这是一份面向Android开发者的复习指南,成功入职字节跳动

前言 19年6月份从网易云音乐离开&#xff0c;放弃了留学机会&#xff0c;开始了人生的第一次创业&#xff0c;前后尝试了两个项目&#xff0c;因为个人能力与时机因素都失败了&#xff0c;虽然没能享受到创业所能够带来高杠杆物质上的回报&#xff0c;但是对个人软技能和自我边…

JVM启动参数

不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM、GC的参数&#xff0c;可以极大的减少由于GC工作&#xff0c;而导致的程序运行中断方面的问题&#xff0c;进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程&#xf…

【UOJ 92】有向图的强连通分量

【题目描述】&#xff1a; 有向图强连通分量&#xff1a;在有向图G中&#xff0c;如果两个顶点vi,vj间&#xff08;vi>vj&#xff09;有一条从vi到vj的有向路径&#xff0c;同时还有一条从vj到vi的有向路径&#xff0c;则称两个顶点强连通(strongly connected)。如果有向图G…

这篇文章可以满足你80%日常工作!一线互联网公司面经总结

前言 最近发现大家都喜欢看面试相关的文章&#xff0c;我也跟一波风&#xff0c;总结了一下我面试中所遇到的问题总结&#xff0c;分享一下面试中被问的最多的一些问题。 希望对正在找工作的朋友提供一些帮助。 好了话不多说&#xff0c;进入正题。 作为安卓开发者&#xff…

java并发synchronized 锁的膨胀过程(锁的升级过程)深入剖析(1)

我们先来说一下我们为什么需要锁&#xff1f; 因为在并发情况为了保证线程的安全性&#xff0c;是在一个多线程环境下正确性的概念&#xff0c;也就是保证多线程环境下共享的、可修改的状态的正确性&#xff08;这里的状态指的是程序里的数据&#xff09;&#xff0c;在java程…

MSCRM二次开发实现自动编号功能

功能描述&#xff1a;对客户实体实现自动编号功能&#xff0c;1、2、3、4...... 自动编号存放于属性accountnumber.原  理&#xff1a;在mscrm服务器用一个文本文件存放当前最新编号&#xff0c;每当创建客户记录时在PreCreate事件接口做以下步骤&#xff1a;1、锁定文本文件…

这篇文章可以满足你80%日常工作!成功入职腾讯

什么是中年危机 根据权威数据显示&#xff0c;国内IT程序员鼎盛时期是在25-27岁左右&#xff0c;30岁对于程序员而言完全是一个38线&#xff0c;接着就是转业转岗的事情&#xff0c;这一点在业界也算是一个共识了。 大学毕业步入IT行业普遍年龄也是在22岁左右&#xff0c;然而…

java并发synchronized 锁的膨胀过程(锁的升级过程)深入剖析(2)

接下来我们分析两个批量偏向撤销的相关案例&#xff08;禁止偏向锁延迟的情况下&#xff1a;-XX:UseBiasedLocking -XX:BiasedLockingStartupDelay0&#xff09;&#xff1a; 案例一&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28…

System.Configuration命名空间下的关键类

1.ConfigurationManager和 WebConfigurationManager类&#xff1a; 使用 ConfigurationManager 类&#xff0c;可以访问计算机和应用程序的配置信息。ConfigurationManager 是处理客户端应用程序配置文件的首选方法&#xff1b;不推荐使用任何其他方法。对于 Web 应用程序&…

连续四年百度Android岗必问面试题!Android校招面试指南

前言 刚从阿里面试回来&#xff0c;想和大家分享一些我的面试经验&#xff0c;以及面试题目。 这篇文章将会更加聚焦在面试前需要看哪些资料&#xff0c;一些面试技巧以及一些这次的面试考题。 面试经历 7月确定想走后开始看各种面经&#xff0c;复习基础知识&#xff0c;月…