JavaSE---ThreadLocal
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的更多相关文章
- JavaSe:ThreadLocal
JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...
- 基础1 JavaSe基础
JavaSe基础 1. 九种基本数据类型的大小,以及他们的封装类 boolean 无明确指定 Boolean char 16bits Character byte 8bits Byte short 1 ...
- 回顾javase点滴
数据类型 8种基本数据类型和引用类型 数据类型 占用位数 存储方式 最小值 最大值 默认值 byte 8 1+7 -128(-2^7) 127(2^7-1) 0 short 16 1+15 -3276 ...
- Java中的ThreadLocal使用
ThreadLocal用于下面的场景: 1. 不允许多个线程同时访问的资源 2. 单个线程存活过程只使用一个实例 官方定义如下: This class provides thread-local va ...
- JavaSE 面试题总结
一. JavaSE 4 1. 面向对象的特征有哪些方面 4 2. String是最基本的数据类型吗? 4 3. super()与this()的区别? 4 4. JAVA的事件委托机制和垃圾回收机制 4 ...
- 抛出这8个问题,检验一下你到底会不会ThreadLocal,来摸个底~
0.问题 和Synchronized的区别 存储在jvm的哪个区域 真的只是当前线程可见吗 会导致内存泄漏么 为什么用Entry数组而不是Entry对象 你学习的开源框架哪些用到了ThreadLoca ...
- 面试官:看你简历说写精通ThreadLocal,这几道题你都会吗?
问题 和Synchronized的区别 存储在jvm的哪个区域 真的只是当前线程可见吗 会导致内存泄漏么 为什么用Entry数组而不是Entry对象 你学习的开源框架哪些用到了ThreadLocal ...
- ThreadLocal不好用?那是你没用对!
在 Java 中,如果要问哪个类使用简单,但用好最不简单?我想你的脑海中一定会浮现出一次词--"ThreadLocal". 确实如此,ThreadLocal 原本设计是为了解决 ...
- ThreadLocal简单理解
在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
随机推荐
- linux 下errno各个值的意义(转) errno.h
strerror(errno):获取errno对应的错误 查看错误代码errno是调试程序的一个重要方法.当linux C api函数发生异常时,一般会将errno变量(需include errno. ...
- create-react-app使用的问题
// 设置 npm config set registry https://registry.npm.taobao.org // 验证是否成功 npm config get registry或npm ...
- CodeForces - 311B:Cats Transport (DP+斜率优化)
Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight r ...
- 洛谷P3373线段树模板2
题目:https://www.luogu.org/problemnew/show/P3373 带乘的线段树,更新时把加的标记也乘一下,然后取值时先乘后加. 代码如下: #include<iost ...
- HL7 ADT Message Sample
http://pixpdqtests.nist.gov:8080/#tests%2Fdriver%2Fversion.htm 可以打开上述连接, 选中version和actor, 然后获取对于samp ...
- javascript 中的深复制 和 其实现方法
首先,我们需要明白什么是深复制(侧重指对象方面)? 在javascript中,复制分为浅复制和深复制,个人理解,浅复制就是直接将引用复制,复制前后的两个对象指向同一个内存地址,对其中一个进行操作,另外 ...
- docker基于宿主机系统版本创建镜像
这里讲如何定制自己centos镜像,仅供测试docker使用. A) 安装软件 yum -y install febootstrap B)下载镜像febootstrap -i bash -i wget ...
- JS---设置简易红绿灯
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Docker入门(三):容器(Containers)
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- R 中数据导入
R语言数据导入 数据导入 1.保存和加载R的数据(与R.data的交互:save()函数和load()函数) a <- 1:10 save(a, file = "data/dumDa ...