1、Java为线程安全提供了工具类,如ThreadLocal等;

2、ThreadLocal类是一个   线程局部变量  ,通过将  ”数据“  放在ThreadLocal中,即可在每条线程中创建一个   ”该数据的拷贝“,从而避免并发访问的线程安全问题;

3、ThreadLocal不能代替同步机制,两者面向的领域不同:

  同步机制:为了同步  多个线程对相同资源的并发访问;

  ThreadLocal:隔离多个线程的资源共享,从根本上避免了多个线程对相同资源的共享冲突;

4、案例:

  使用Filter+ThreadLocal实现在Controller、Service中直接使用某个线程安全对象

  a,web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="false">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring.xml
</param-value>
</context-param> <listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <filter>
<filter-name>encodingFilter</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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!--MyFilter测试-->
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.exiuge.filtertest.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 -->
<!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> -->
<!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 -->
<!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由servlet container管理 -->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!--阿里Druid内置提供了一个StatViewServlet用于展示Druid的统计信息-->
<!--http://server:port/appname/druid/index.html-->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping> </web-app>

   b,MyFilter

package com.exiuge.filtertest.filter;

import com.exiuge.filtertest.entity.User;
import com.exiuge.filtertest.entity.UserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException; public class MyFilter implements Filter { private static final Logger LOGGER= LoggerFactory.getLogger(MyFilter.class); @Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.debug("myFilter init...");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
User user=new User("jack",18,"man");
UserContext.set(user);
filterChain.doFilter(servletRequest,servletResponse);
UserContext.remove();
} @Override
public void destroy() { }
}

  c,User

package com.exiuge.filtertest.entity;

import java.io.Serializable;

public class User implements Serializable {

    private String name;
private int age;
private String sex; public User(){ } public User(String name,int age,String sex){
this.name=name;
this.age=age;
this.sex=sex;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} @Override
public String toString() {
return this.name+this.age+this.sex;
}
}

  d,UserContext

package com.exiuge.filtertest.entity;

public class UserContext{

    private static final ThreadLocal<User> LOCAL_USER=new ThreadLocal<User>();

    public static User get() {
return LOCAL_USER.get();
} public static void set(User user){
LOCAL_USER.set(user);
} public static void remove(){
LOCAL_USER.remove();
}
}

  e,MyController

package com.exiuge.filtertest.controller;

import com.exiuge.filtertest.entity.User;
import com.exiuge.filtertest.entity.UserContext;
import com.exiuge.filtertest.service.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Objects; @Controller
@RequestMapping(value = "/myFilter")
public class MyController { private static final Logger LOGGER= LoggerFactory.getLogger(MyController.class); @Autowired
private MyService myService; @RequestMapping(value = "/test")
public String test(){
User user= UserContext.get();
if (Objects.nonNull(user)){
LOGGER.debug("controller:"+user.toString());
myService.test();
}
return "MyFilter Test...";
}
}

  f,MyService

package com.exiuge.filtertest.service;

import com.exiuge.filtertest.entity.User;
import com.exiuge.filtertest.entity.UserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.Objects; @Service
public class MyService { private static final Logger LOGGER= LoggerFactory.getLogger(MyService.class); public void test(){
User user = UserContext.get();
if (Objects.nonNull(user)){
LOGGER.debug("service:"+user.toString());
}
}
}

JavaSE---ThreadLocal的更多相关文章

  1. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  2. 基础1 JavaSe基础

    JavaSe基础 1. 九种基本数据类型的大小,以及他们的封装类 boolean 无明确指定 Boolean char 16bits Character byte 8bits Byte short 1 ...

  3. 回顾javase点滴

    数据类型 8种基本数据类型和引用类型 数据类型 占用位数 存储方式 最小值 最大值 默认值 byte 8 1+7 -128(-2^7) 127(2^7-1) 0 short 16 1+15 -3276 ...

  4. Java中的ThreadLocal使用

    ThreadLocal用于下面的场景: 1. 不允许多个线程同时访问的资源 2. 单个线程存活过程只使用一个实例 官方定义如下: This class provides thread-local va ...

  5. JavaSE 面试题总结

    一. JavaSE 4 1. 面向对象的特征有哪些方面 4 2. String是最基本的数据类型吗? 4 3. super()与this()的区别? 4 4. JAVA的事件委托机制和垃圾回收机制 4 ...

  6. 抛出这8个问题,检验一下你到底会不会ThreadLocal,来摸个底~

    0.问题 和Synchronized的区别 存储在jvm的哪个区域 真的只是当前线程可见吗 会导致内存泄漏么 为什么用Entry数组而不是Entry对象 你学习的开源框架哪些用到了ThreadLoca ...

  7. 面试官:看你简历说写精通ThreadLocal,这几道题你都会吗?

    问题 和Synchronized的区别 存储在jvm的哪个区域 真的只是当前线程可见吗 会导致内存泄漏么 为什么用Entry数组而不是Entry对象 你学习的开源框架哪些用到了ThreadLocal ...

  8. ThreadLocal不好用?那是你没用对!

    在 Java 中,如果要问哪个类使用简单,但用好最不简单?我想你的脑海中一定会浮现出一次词--"ThreadLocal". ​ 确实如此,ThreadLocal 原本设计是为了解决 ...

  9. ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...

  10. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

随机推荐

  1. 插件_热部署_JRebel

    一.License Server 1.运行反向代理 GitHub地址:https://github.com/ilanyu/ReverseProxy 下载地址:ReverseProxy_windows_ ...

  2. python 列表之队列

    列表实现队列操作(FIFO),可以使用标准库里的 collections.deque,deque是double-ended quene的缩写,双端队列的意思,它可以实现从队列头部快速增加和取出对象. ...

  3. Codeforces 762B USB vs. PS/2 贪心

    Codeforces 762B 题目大意: 有a台只有USB接口的电脑,b台PS/2接口的电脑,c台两种接口都有的电脑.每台电脑只用装一个鼠标.给出n个鼠标及其费用,每个鼠标只能使用一遍.在最大化有鼠 ...

  4. jquery.one()

    one() 方法为被选元素附加一个或多个事件处理程序,并规定当事件发生时运行的函数. 当使用 one() 方法时,每个元素只能运行一次事件处理器函数. 也就是,绑定的function,只会执行一次. ...

  5. git简单获取远程某个分支代码命令

    git clone resource.git git branch -a list all the local and remote branches git checkout [remote bra ...

  6. java 通过System.getProperties()获取系统参数

    转自:https://www.cnblogs.com/ksuifeng/archive/2010/09/25/1834416.html 1.java的System.getProperty()方法可以获 ...

  7. 【250】◀▶IEW-Unit15

    Unit 15 Youth Issues 1.model1题目分析 Young people who are still at school often feel just as much stres ...

  8. phpcms后台栏目权限修改无效的原因和解决方法

    现象:在phpcms后台中,新建角色,然后修改角色对应栏目权限,结果一直只能选择一半数量的栏目.剩下的栏目怎么修改都不生效. 对比: step1:再另一个phpcms后台做同样操作,依旧是这个结果.跟 ...

  9. 正则表达式/i,/g,/ig,/gi,/m的含义

    正则表达式中/i,/g,/ig,/gi,/m的区别和含义 /i (忽略大小写)/g (全文查找出现的所有匹配字符)/m (多行查找)/gi(全文查找.忽略大小写)/ig(全文查找.忽略大小写)

  10. POJ - 2377 Bad Cowtractors Kru最大生成树

    Bad Cowtractors Bessie has been hired to build a cheap internet network among Farmer John's N (2 < ...