`

Java基础知识系列:线程变量

阅读更多

问题场景一:

      Web应用中,后台一般都分成几层,最常用的分法有控制层、业务逻辑层、数据持久层和表现层。一般情况下,我们都会把当前用户存放在HttpSession里面。怎么获取到当前用户的信息呢?首先,要获得HttpServletRequest对象,然后通过它的getSession()方法获取HttpSession对象,从而根据对应的Key值拿到用户信息。

      现在我们提出一个新的要求,在控制层、业务逻辑层、数据持久层和表现层都能方便的获取到当前用户的信息。怎么实现呢?

      想一想,发现了两种方法:

(1)控制层肯定可以拿到HttpServletRequest对象,所以控制层是可以获取到用户信息的,那么业务逻辑层、数据持久层和表现层怎么办呢?最直接的方法就是在上层调用下层的时候通过方法参数传下去。这样各个层的都能获得HttpServletRequest对象。那么就可以实现各层获取当前用户的信息了。

 

(2)新建一个类,类里面有一个静态Map,一开始的时候,将当前HttpServletRequest保存到这个类的Map中,问题是放进去后,我们凭什么拿出来呢?Map的key值放什么好呢?必须放一个到处都可以拿到的对象,并且可以表示我当前这个请求。我们想到了当前线程,Servlet容器对于每个请求都有一个线程来处理的,所以一个请求处理时间内,一个线程可以唯一标识一个请求。那么,我们就那当前线程对象作为Map的key值,value值为HttpServletRequest对象。这样我们再通过这个类的一个静态方法,传入当前线程对象从而获得HttpServletRequest对象,从而获取到当前用户的信息。

 

问题场景二:

      一个请求的处理涉及几次数据库操作,假如这几次数据库操作都是针对同一个数据库用户的。正常情况下,JDBC执行的顺序是:

(1)获取一个数据库连接

(2)数据库操作1

(3)数据库操作2

(4)组装结果数据

(5)是释放连接回连接池

 

但是,很多封装好的持久层框架(比如Spring、Ibatis等)的执行顺序是这样的:

 

(1)获取一个数据库连接

(2)数据库操作1

(3)组装结果数据

(4)是释放连接回连接池

 

(5)获取一个数据库连接

(6)数据库操作2

(7)组装结果数据

(8)是释放连接回连接池

 

就第二种情况,两次的数据库操作是分开的,怎么保证两次数据库操作能在同一个事务里面,我们知道同一个事务的前提是两次操作的数据库连接要是同一个才行。所以怎么保证,一次请求的处理过程中,都在同一个事务中。说白了,就是怎么保证一次请求处理的过程中,拿到的数据库连接永远是同一个。

     这个时候,我们就回想到,能不能跟场景一一样,让连接跟线程绑定,每次获取到的数据库连接都会是同一个。

 

线程变量实现

 

(1)自己动手实现:

public class ThreadVariable {
	private static Map variableMap = new HashMap();
	
	public static void addVariable(String variableName,String variableValue){
		Map map = null;
		Long threadId = Thread.currentThread().getId();
		if(variableMap.containsKey(threadId)){
			map = (Map)variableMap.get(threadId);
		}
		else{
			map = new HashMap();
			variableMap.put(threadId, map);
		}
		
		map.put(variableName, variableValue);
	}
	
	public static Object getVariable(String variableName) throws Exception{
		Long threadId = Thread.currentThread().getId();
		if(variableMap.containsKey(threadId)){
			Map map = (Map)variableMap.get(threadId);
			return map.get(variableName);
		}
		else{
			throw new Exception("the variable [" + variableName + "] does not exist");
		}
	}
	
	public static boolean removeVariable(String variableName){
		try{
			variableMap.remove(variableName);
			return true;
		}catch(Exception e){
			return false;
		}
	}

}

 

(2)使用JDK本身支持的ThreadLocal对象

private static final ThreadLocal context = new ThreadLocal();

context.set("zhangsan");

Object object = context.get();
 

 

使用总结:

(1)解决多线程并发的资源共享问题,每一个线程提供一个独立的变量副本,从而隔离了多个线程对访问数据的冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。

 

注意:并不是所有使用同步的地方都可以改用线程变量的方式,因为有些数据是必须要保持全局的唯一、一致性的,这种情况下如果使用线程变量则会有多份不一致的副本。

 

 

(2)保证一个线程所涉及的各个层次的代码都可能访问到同一个线程的变量。

比如:怎么保证一次线程处理的数据库操作能够统一提交?事务的统一提交是有前提的,都使用同一个Connection对象。



对于多线程资源共享的问题,我们比较一下同步机制和线程变量的区别:
(1)同步机制采用了“以时间换空间”的方式:访问串行化,数据共享化。多个线程同时访问同一个资源需要排队等候。

(2)线程变量采用了“以空间换时间”的方式:访问并行化,为每一个线程都提供了一份变量。


分享到:
评论

相关推荐

    Java基础知识大全《自学宝典》

    java自学宝典:java 如何实现线程的安全:线程的同步机制 * 方式一:同步代码块 * synchronized(同步监视器){ * //需要被同步的代码块(即为操作共享数据的代码) * } * 1.共享数据:多个线程共同操作的同一个数据...

    Java学习用例demo

    java基础知识点: 1、Java语言基础:包括环境搭建、基本数据类型、包装类、变量、常量定义、控制结构、String字符串处理等; 2、Java语言面向对象:面向对象思想、类声明与对象实例化、成员变量、方法重载,封装性...

    Java核心技术 卷1 基础知识 原书第9版

    《Java核心技术·卷1:基础知识(原书第9版)》共14章。第1章概述了Java语言与其他程序设计语言不同的性能;第2章讲解了如何下载和安装JDK及本书的程序示例;第3章介绍了变量、循环和简单的函数;第4章讲解了类和...

    Java核心技术 卷Ⅰ:基础知识 【中文】(第八版)

    这一章涉及的基础知识有变量、循环以及简单的函数。对于C或 C++程序员来说,学习这一章的内容将会感觉一帆风顺,因为这些语言特性的语法本质上与C 语言相同。对于没有C语言程序设计背景,但使用过其他程序设计语言...

    Java基础(韩顺平版)笔记详

    有经验的开发者,希望重温Java基础知识或参考韩顺平的教学风格。 使用场景及目标 初学者入门:为无编程背景的学员提供Java语言的基础知识。 课程学习:作为计算机科学课程的辅助教材,帮助学生深入理解Java。 技能...

    并发编程基础知识,java内存模型及多线程、volatile

    Java内存模型,即:JMM。当程序执⾏并⾏操作时,如果对数据的访问和操作不加以控制,那么必 然会对程序的正确性造成破坏。因此,我们需要在深⼊了解并⾏机制的前提下,再定义⼀种规则, 来保证多个线程间可以有效地...

    教学课件+Java基础知识+PPT课程+Java教学

    Java基础知识课件 1. 引言 Java是一种广泛使用的编程语言,以其跨平台兼容性和健壮性而闻名。Java最初由Sun Microsystems(现为Oracle Corporation的一部分)开发,并于1995年发布。 2. Java的特点 -跨平台兼容性:...

    并发编程实践,全面介绍基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具、Executor部分等

    基础知识   并发与并行   Java并发演进历史   Java并发模型   线程模型   存储模型 JVM同步原语 volatile CAS 线程安全   保护“共享数据” 低级并发工具   原子变量   锁(内部锁和显式锁) 线程安全容器...

    2023Java高频面试题

    Java基础知识:Java的基本数据类型、变量、运算符、控制语句等基础概念。 面向对象编程:类、对象、封装、继承、多态等面向对象编程的基础知识。 Java集合框架:常用的List、Set、Map等集合类及其实现方式、使用场景...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...

    Tjcug#JavaBasciLearing#Java基础:由JVM内存模型详解线程安全1

    1.前言最近在研究JVM内存模型和Java基础知识。主要讲的是线程共享变量与线程私有变量以及如何写出线程安全的代码。这里列出一条规则,“类中的成员变量,也叫实例

    java基础知识文档

    适合Java入门同学,数据类型/变量数组/集合/反射/异常/多线程/设计模式/io流/网络编程/等等

    Java面试题合集最新版2024.zip

    Java面试通常涵盖多个方面,包括Java基础知识、编程技能、问题解决能力,以及对Java生态系统和相关技术的理解。以下是一些建议的Java面试准备要点和资源描述: 一、Java基础知识 数据类型、变量与运算符:理解Java...

    java课件(java的基础的知识,包括接口,线程,网络,基本变量和数据库编程等)

    主要是java的基础的知识,包括接口,线程,网络,基本变量和数据库编程等

    java面试常用知识点.docx

    Java基础:变量、数据类型、运算符、条件语句、循环语句、数组、集合、异常处理等 面向对象:类、继承、多态、包、接口、抽象类、泛型等 异常处理:try-catch-finally、异常分类及处理、自定义异常等 线程:线程创建...

    Java基础知识点.html

    Java基础思维导图对应html版本资源: 类加载器 ClassLoader 反射 Stream 流 函数式编程 Lambda 表达式 网络编程-协议 网络编程-端口 网络编程-IP 多线程 IO流-字节流 IO流-字符流 IO流-转换流 File Map HashMap ...

    【Java基础知识】全面涵盖了JavaSE的知识点笔记

    可以用于面试过一下基础知识点,知识点包含:变量、数据类型、运算符、控制语句、面向对象编程、异常机制、集合(容器)、IO流、多线程、网络编程、反射

    《Java核心技术+卷1:基础知识(原书第9版)》

    《Java核心技术+卷1:基础知识(原书第9版)》 《Java核心技术·卷1:基础知识》共14章。第1章概述了Java语言与其他程序设计语言不同的性能;第2章讲解了如何下载和安装JDK及本书的程序示例;第3章介绍了变量、循环...

    Java领域基础部分JavaSE笔记

    职业开发者:需要回顾或巩固Java基础知识的专业人士。 使用场景及目标 学习基础:为初学者提供一个全面的Java入门指南。 课程辅助:作为大学课程或在线教程的补充材料。 技能提升:帮助有经验的开发者回顾和加强Java...

    Java基础语法面试题.docx

    Java基础语法面试题资源通常是指帮助准备Java编程面试的问题集合,涵盖了Java编程语言的基础概念、语法、特性和常见问题。这些资源可以帮助面试者巩固和扩展他们的Java知识,准备应对面试过程中的技术问题。 这些...

Global site tag (gtag.js) - Google Analytics