并发都用到, 两个都是解决了线程并发问题,区别呢?

Synchronized  同步机制, 共有变量被多个线程使用,会出现线程不安全,所以,加锁,锁机制很多种,例如Synchronized, lock 锁, 阻塞队列。以时间换空间, 某一个线程拿到锁, 先进去, 其他线程, 等着吧~

ThreadLocal ,当多个线程使用一个对象, 以空间换时间, 创建不同的变量副本。大家不要抢, 每个人都有!首先这个对象是全局变量。

ThreadLocal 保证了线程的隔离性 ,一个经典的例子是 SimpleDateFormat 线程不安全问题, 这个时间格式化 工具类我们使用频率非常大 。

Synchronized使用场景:比如1000 张火车票, 每个线程操作, 必须保证每个窗口卖 不同 的火车票, 保证座位不相同! 这1000 张票是原子性的。

ThreadLocal使用场景:举例: spring security管理权限  , 每个用户用户名,密码验证登录会存在 Authentication中, 包括用户名密码, 是否被锁定, 是否过期,等很多消息, 这是一个对象, 当用户登录之后, 使用这个系统, 比如查看自己的订单,自己的购物车,自己的余额 ,这里Authentication 就是全局变量,如果多个用户登录,这个对象肯定会被改变, 简单的方法是 每一个用户 授权登录后, 都生成一个全局变量对象, 但是1000 万 个用户呢,系统会不会垮掉?肯定是!

这就是线程并发非同步的另一种领域,数据隔离,保证每个用户有各自的数据, 用同步加锁是不能解决的。

所以可以创建一个threadLocal , 看看  spring security 的源码:

/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.security.core.context; import org.springframework.util.Assert; /**
* A <code>ThreadLocal</code>-based implementation of
* {@link SecurityContextHolderStrategy}.
*
* @author Ben Alex
*
* @see java.lang.ThreadLocal
* @see org.springframework.security.core.context.web.SecurityContextPersistenceFilter
*/
final class ThreadLocalSecurityContextHolderStrategy implements
SecurityContextHolderStrategy {
// ~ Static fields/initializers
// =====================================================================================
//核心在这里 , 这里创建 一个 threadLocal 的 SecurityContext
private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<SecurityContext>(); // ~ Methods
// ======================================================================================================== public void clearContext() {
contextHolder.remove();
} public SecurityContext getContext() {
SecurityContext ctx = contextHolder.get(); if (ctx == null) {
ctx = createEmptyContext();
contextHolder.set(ctx);
} return ctx;
} public void setContext(SecurityContext context) {
Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
contextHolder.set(context);
} public SecurityContext createEmptyContext() {
return new SecurityContextImpl();
}
}

再看看线程全局变量怎么被设置进去

       //这个是登录方法, 用户名密码登录
public void login(String username, String password) throws ServletException {
if (isAuthenticated()) {
throw new ServletException("Cannot perform login for '" + username
+ "' already authenticated as '" + getRemoteUser() + "'");
}
AuthenticationManager authManager = authenticationManager;
if (authManager == null) {
logger.debug("authenticationManager is null, so allowing original HttpServletRequest to handle login");
super.login(username, password);
return;
}
Authentication authentication;
try {
//这里去数据库验证, 用户名错误?用户名过期?用户被锁定?用户什么角色
authentication = authManager
.authenticate(new UsernamePasswordAuthenticationToken(username,
password));
}
catch (AuthenticationException loginFailed) {
SecurityContextHolder.clearContext();
throw new ServletException(loginFailed.getMessage(), loginFailed);
}
//这里全是全局变量 设置进去
SecurityContextHolder.getContext().setAuthentication(authentication);
}

好了, 一个验证通过了, 并被设置到threadLocal ,

现在用户删除订单

    @RequestMapping(value = "/deleteId", method = RequestMethod.POST)
@ResponseBody
public JSONObject deleteId(@RequestParam("strJson")String json) {
//SecurityContextHolder 是一个全局变量, 直接在方法里面获取
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
Integer role=-1;
Object pinciba = auth.getPrincipal();
if (pinciba instanceof Customer) {
role =((Customer) pinciba).getRole();
} if(role==2){
//管理员删除
}else{
//非管理员不能删除
}
JSONObject jsons = new JSONObject();
System.out.println(json);
return jsons;
}

threadlocal 很强大, 一种弱引用。我们知道Java有四中对象:

从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

threadLocal 就是一种弱引用, 当某个用户很长时间没有登录, 而 其他用户需要threadLocal 添加一个自己的 变量, 就会回收没有使用了, 实现了线程数据隔离吧。

最新文章

  1. GJM :Unity使用EasyAR实现脱卡功能
  2. selenium 下载百度音乐并验证
  3. linux系统meminfo详解(待补充)
  4. 使用XStream解析MXL文件用到的jar包---xpp3_min-1.1.3.4.O.jar和xstream-1.3.1.jar
  5. JQuery实现table分页
  6. iOS 推送所调用的函数详解
  7. N Sum
  8. ORACLE-Kill 杀死正在执行的Oracle存储过程和死锁语句
  9. 创建OpenStack外部网络并分配浮动IP
  10. java 重写的学习
  11. adb 安装apk 报错:Failure [INSTALL_FAILED_CPU_ABI_INCOMPATIBLE]
  12. ini文件必须要全路径名啊
  13. 遍历CheckBox根据指定条件做筛选js
  14. js中时间戳与日期格式的相互转换
  15. How to enable flash on Chromium
  16. 关于Spring-Data-Jpa的一些理解
  17. jquery 圆形进度条
  18. DataTable使用技巧:DataRowState
  19. pycharm连接数据库出现时区jdbc问题
  20. 在Delphi中动态地使用SQL查询语句 Adoquery sql 参数 冒号

热门文章

  1. Linux系统调优
  2. wysiwyg editor
  3. xcode 升级插件失效问题
  4. EF4 Code First和EF6 Code First链接mysql的方法
  5. caller和callee的区别
  6. BZOJ 1624: [Usaco2008 Open] Clear And Present Danger 寻宝之路
  7. 【技术贴】解决Mysql ERROR 1045 (28000): Access denied for
  8. CPU,MPU,MCU,SOC,SOPC联系与差别
  9. Java+JQuery实现网页显示本地文件目录(含源码)
  10. 《鸟哥的Linux私房菜》读书笔记三