`

多线程(二)ThreadLocal 学习记录+代码

 
阅读更多

初学多线程的时候,错认将ThreadLocal理解为“本地线程 ”,后来仔细研究一翻,发现根本不是这回事儿。

ThreadLocal相当于一个大Map集合,为每个使用该变量的线程提供独立的变量副本,每个副本的改变不会影响到其它副本,为多线程环境中并发访问问题提供了一种隔离机制就像改变map集合里key对应value的值并不会影响到其它value值一样。特别注意:synchronized和ThreadLocal容易混淆。这两个概念中Synchronized是为线程间的数据共享提供锁的机制而ThreadLocal主要用于线程间的数据隔离访问。再举个简单例子: 一个公寓里 ,有线电视信号统一接入,家家户户都在看电视,所有住户的换台行为是多线程并发执行并且只能控制自家的电视,不能因为你按个遥控器把邻居家的电视频道给换了。

ThreadLocal类在jdk1.6中共有四个方法:

 T get()
          返回此线程局部变量的当前线程副本中的值。相当于map中的get方法,key值是默认取当前线程名。
protected  T initialValue() 返回此线程局部变量的当前线程的“初始值”。线程第一次使用 get() 方法访问变量时将调用此方法,但如果线程之前调用了 set(T) 方法,则不会对该线程再调用 initialValue 方法。通常,此方法对每个线程最多调用一次,但如果在调用 get() 后又调用了 remove(),则可能再次调用此方法。
 void remove()
          移除此线程局部变量当前线程的值。
 void set(T value)
          将此线程局部变量的当前线程副本中的值设置为指定值。

 

 下面就以公寓里住户看电视为例编写代码:

 

第一段代码:先演示不使用ThreadLocal的例子  ,一户人家看电视换台效果  。 

 

package family;

import java.util.ArrayList;
import java.util.List;

public class OwnHome {
	
	//测试方法
	static public void main(String[] args){
		   System.out.println("打开电视机==================================");
	        for (int i = 0; i < OwnHome.tv.size(); i++) {
	           String tvname= OwnHome.change(i) ;  //拿遥控器换频道
	            try {
	                Thread.sleep(100); //看电视的过程
	                
	                System.out.println(tvname+"是新闻联播,准备换台~") ;
	            } catch (InterruptedException e) {
	            }
	        }
	       
	        System.out.println("关掉电视机====================================");
	}
	private static List<String> tv=new ArrayList<String>() ; //先new 一个电视 ,里面包含多个频道
	
	static {
		tv.add("cctv1") ;
		tv.add("cctv2") ;
		tv.add("cctv3") ;
		tv.add("cctv4") ;
		tv.add("cctv5") ;
		tv.add("凤凰卫视") ;
	}
	
	public static String change(int n){
		
		String tvname =tv.get(n) ;
		System.out.println("将频道换切换到"+tvname) ;
		return tvname ;
	}
	
}

 最终结果:

打开电视机==================================
将频道换切换到cctv1
cctv1是新闻联播,准备换台~
将频道换切换到cctv2
cctv2是新闻联播,准备换台~
将频道换切换到cctv3
cctv3是新闻联播,准备换台~
将频道换切换到cctv4
cctv4是新闻联播,准备换台~
将频道换切换到cctv5
cctv5是新闻联播,准备换台~
将频道换切换到凤凰卫视
凤凰卫视是新闻联播,准备换台~
关掉电视机====================================

 第二段代码:用ThreadLocal 演示所有住户都在看电视的换台效果

 

package family;

import java.util.ArrayList;
import java.util.List;

public class OwnHome {
	
	public OwnHome() {
		
	}
	private static List<String> tv=new ArrayList<String>() ; //先new 一个电视 ,里面包含多个频道
	
	static {
		tv.add("cctv1") ;
		tv.add("cctv2") ;
		tv.add("cctv3") ;
		tv.add("cctv4") ;
		tv.add("cctv5") ;
		tv.add("凤凰卫视") ;
	}
	
	public static String change(int n){
		
		String tvname =tv.get(n) ;
		System.out.println(Thread.currentThread().getName()+"将频道换切换到"+tvname) ;
		return tvname ;
	}
	
}

 

package family;

public class ThreadLocalHomes {
	//一般都声明在静态变量中,如果不断的创建ThreadLocal而不remove,有可能会导致内存泄露
	private static final ThreadLocal  local =new ThreadLocal() ;
	
	
	/*
	 *  返回当前线程对应的自家电视
	 */
	public static OwnHome getHome(){
		
		OwnHome   home =(OwnHome) local.get() ;
		if(home==null){
			home=new OwnHome() ;
			local.set(home) ;
		}
		return home ;
	}

}

 

package family;

public class ClientThread extends Thread {
    public ClientThread(String name) {
        super(name);
    }
    public void run() {
    	 System.out.println(getName());
        for (int i = 0; i < 6; i++) {
        	ThreadLocalHomes.getHome().change(i) ;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
        System.out.println(getName() + "看完电视,睡觉休息了");
 
    }
}

 

package family;

public class TestThreadLocal {
	
	
	static public void main(String[] args){
		
		//模拟三个家庭在看电视
		
		new ClientThread("张三,长虹牌电视机 ").start() ;
		new ClientThread("嘉欣,康佳牌电视机 ").start() ;
		new ClientThread("双儿,飞利浦牌电视机 ").start() ;
	
	}

}

 输出结果:

张三,长虹牌电视机
嘉欣,康佳牌电视机
双儿,飞利浦牌电视机
张三,长虹牌电视机 将频道换切换到cctv1
双儿,飞利浦牌电视机 将频道换切换到cctv1
嘉欣,康佳牌电视机 将频道换切换到cctv1
张三,长虹牌电视机 将频道换切换到cctv2
嘉欣,康佳牌电视机 将频道换切换到cctv2
双儿,飞利浦牌电视机 将频道换切换到cctv2
张三,长虹牌电视机 将频道换切换到cctv3
嘉欣,康佳牌电视机 将频道换切换到cctv3
双儿,飞利浦牌电视机 将频道换切换到cctv3
张三,长虹牌电视机 将频道换切换到cctv4
嘉欣,康佳牌电视机 将频道换切换到cctv4
双儿,飞利浦牌电视机 将频道换切换到cctv4
张三,长虹牌电视机 将频道换切换到cctv5
嘉欣,康佳牌电视机 将频道换切换到cctv5
双儿,飞利浦牌电视机 将频道换切换到cctv5
双儿,飞利浦牌电视机 将频道换切换到凤凰卫视
嘉欣,康佳牌电视机 将频道换切换到凤凰卫视
张三,长虹牌电视机 将频道换切换到凤凰卫视
张三,长虹牌电视机 看完电视,睡觉休息了
嘉欣,康佳牌电视机 看完电视,睡觉休息了
双儿,飞利浦牌电视机 看完电视,睡觉休息了

 结束 。或许理解有偏差 ,还请各位大神多多指教。

 

分享到:
评论

相关推荐

    ThreadLocal原理及在多层架构中的应用

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的概念,主要用于在多线程环境中为每个线程提供独立的变量副本。ThreadLocal不是一种数据结构,而是一种解决线程间共享数据的方式,它提供了线程安全的局部...

    java事务 - threadlocal

    Java事务和ThreadLocal是两种在Java编程中至关重要的概念,它们分别用于处理多线程环境下的数据一致性问题和提供线程局部变量。 首先,我们来深入理解Java事务。在数据库操作中,事务是一系列操作的集合,这些操作...

    正确理解ThreadLocal.pdf

    3. **日志记录**:在多线程环境中,`ThreadLocal`可以用于维护每个线程的日志上下文,如线程ID、用户名等,便于日志信息的记录和分析。 4. **性能优化**:在某些计算密集型应用中,`ThreadLocal`可以用于缓存线程...

    java中ThreadLocal类的使用

    - **代码可读性和可维护性**:`ThreadLocal`的使用可能使代码变得复杂,不易于理解和调试,尤其是在多线程环境下的问题排查。 总结,`ThreadLocal`是Java中用于实现线程局部变量的工具,它提供了一种简单的方式在多...

    多线程-狂神说Java学习笔记

    本学习笔记将深入探讨Java多线程的相关知识,包括其原理、实现方式、同步机制以及常见问题。 ### 一、多线程的基本概念 多线程是指在一个程序中存在两个或更多的执行线程,这些线程共享同一内存空间,但各自拥有...

    C# 高效线程安全,解决多线程写txt日志类.zip

    "C# 高效线程安全,解决多线程写txt日志类.zip" 提供了一个专门用于多线程环境下写入txt日志文件的解决方案,确保了在并发写入时的数据一致性与程序稳定性。 首先,我们要理解什么是线程安全。线程安全是指当多个...

    java多线程学习笔记

    在本文中,我们将深入探讨Java多线程的相关知识点,并结合提供的源代码进行学习。 1. **线程的创建** - **实现Runnable接口**:创建一个类实现Runnable接口,然后将其实例传递给Thread类的构造函数,如`Thread t =...

    Java多线程源码笔记.pdf

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,从而提高系统效率。在Java中,实现多线程主要有两种方式:通过继承Thread类和实现Runnable接口。Thread类提供了创建新线程的基本功能,而Runnable...

    java线程学习笔记

    Java线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...

    c#多线程编程笔记

    本笔记将深入探讨C#中的多线程编程,包括其基本概念、创建线程的方式、线程同步与互斥、线程安全以及线程池的使用。 ### 1. 基本概念 - **线程**:线程是程序的执行流程,每个进程至少包含一个线程。多线程意味着...

    java分布式应用学习笔记05多线程下的并发同步器.pdf

    在Java分布式应用开发中,多线程环境下的并发同步是至关重要的一个环节。并发同步器在多线程编程中起到协调各个线程访问共享资源,确保数据一致性与程序正确性的关键作用。本篇笔记将深入探讨Java中的并发同步机制,...

    Python之ThreadLocal共4页.pdf.zip

    理解并熟练使用ThreadLocal是Python开发者在处理多线程程序时必备的技能之一。 在Python的`threading`模块中,`threading.local()`函数返回一个ThreadLocal对象。这个对象的特性是它的属性总是与创建它的线程绑定,...

    ThreadLocal 线程本地变量 及 源码分析.rar_开发_设计

    ThreadLocal是Java编程语言中的一个类,用于在多线程环境下提供线程局部变量。它为每个线程创建了一个独立的变量副本,每个线程只能访问自己的副本,不会影响其他线程。这种机制有助于实现线程安全,尤其在需要线程...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第二阶段38讲、多线程Active Objects设计模式(接受异步消息的主动对象)-上.mp4 │ 高并发编程第二阶段39讲、多线程Active Objects设计模式(接受异步消息的主动对象)-中.mp4 │ 高并发编程第二阶段40...

    ThreadLocal使用案例_动力节点Java学院整理

    我们使用ThreadLocal来记录操作日志,以便在多线程环境中能够正确地记录操作日志。通过使用ThreadLocal,我们可以确保数据的一致性和线程安全。 ThreadLocal的使用可以带来许多好处,例如: * 实现线程安全的变量...

    【面试必看】多线程笔记.pdf

    在Java编程中,多线程是并发处理的基础,它允许程序同时执行多个任务,从而提高系统效率。然而,多线程编程也带来了一些挑战和问题,这在面试中是常被问及的知识点。 首先,线程安全问题是多线程环境中最常见的问题...

    多线程加签验签例子.zip

    “多线程加签验签例子.txt”文件很可能是详细阐述这个示例的代码或文档,包括如何在多线程中创建签名生成和验证的线程,以及如何管理共享资源,比如密钥对和签名结果的存储。可能涉及到的关键技术包括: 1. **线程...

    Java分布式应用学习笔记03JVM对线程的资源同步和交互机制

    5. **线程间通信**:除了锁机制,JVM还提供了一系列的线程间通信工具,如`ThreadLocal`、`Wait/Notify`、`CountDownLatch`、`Semaphore`、`CyclicBarrier`等,用于解决线程间的同步问题,使多线程程序更加灵活和可控...

Global site tag (gtag.js) - Google Analytics