Java并发编程之ThreadLocal类

ThreadLocal类可以理解为ThreadLocalVariable(线程局部变量),提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程在调用set时设置的最新值。可以将ThreadLocal<T>视为 包含了Map<Thread,T>对象,保存了特定于该线程的值。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

模拟ThreadLocal

    import java.util.Collections; import java.util.HashMap; import java.util.Map;   public class SimpleThreadLocal<T> { private Map<Thread, T> valueMap = Collections .synchronizedMap(new HashMap<Thread, T>());   public void set(T newValue) { valueMap.put(Thread.currentThread(), newValue); // ①键为线程对象,值为本线程的变量副本 }   public T get() { Thread currentThread = Thread.currentThread(); T o = valueMap.get(currentThread); // ②返回本线程对应的变量 if (o == null && !valueMap.containsKey(currentThread)) { // ③如果在Map中不存在,放到Map中保存起来。 o = initialValue(); valueMap.put(currentThread, o); } return o; }   public void remove() { valueMap.remove(Thread.currentThread()); }   protected T initialValue() { return null; } }

实用ThreadLocal

    class Count { private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() { @Override protected Integer initialValue() { return 0; } };   public Integer increase() { count.set(count.get() + 1); return count.get(); }   }   class TestThread implements Runnable { private Count count;   public TestThread(Count count) { this.count = count; }   @Override public void run() { // TODO Auto-generated method stub for (int i = 1; i <= 3; i++) { System.out.println(Thread.currentThread().getName() + "\t" + i + "th\t" + count.increase()); } } }   public class TestThreadLocal { public static void main(String[] args) { Count count = new Count(); Thread t1 = new Thread(new TestThread(count)); Thread t2 = new Thread(new TestThread(count)); Thread t3 = new Thread(new TestThread(count)); Thread t4 = new Thread(new TestThread(count)); t1.start(); t2.start(); t3.start(); t4.start(); } }

输出

Thread-0    1th    1

Thread-0    2th    2

Thread-0    3th    3

Thread-3    1th    1

Thread-1    1th    1

Thread-1    2th    2

Thread-2    1th    1

Thread-1    3th    3

Thread-3    2th    2

Thread-3    3th    3

Thread-2    2th    2

Thread-2    3th    3

来自为知笔记(Wiz)

时间: 2024-12-15 07:15:19

Java并发编程之ThreadLocal类的相关文章

Java并发编程之Phaser类

Phaser这个类的使用场景为N个线程分阶段并行的问题.有这么一个任务为"做3道题",每个学生一个进程,5个学生可以并行做,这个就是常规的并发,但是如果加一个额外的 限制条件,必须等所有人都做完类第一题,才能开始做第二题,必须等所有人都做完了第二题,才能做第三题,这个问题就转变成了分阶段并发的问题,最适合用Phaser来解题,下面给出源代码,大家可以自己尝试: MyPhaser.java import java.util.concurrent.Phaser; public class

Java并发编程之ThreadLocal内存泄漏探究

使用 ThreadLocal 不当可能会导致内存泄露,是什么原因导致的内存泄漏呢? 我们首先看一个例子,代码如下: /** * Created by cong on 2018/7/14. */ public class ThreadLocalOutOfMemoryTest { static class LocalVariable { private Long[] a = new Long[1024*1024]; } // (1) final static ThreadPoolExecutor p

Java并发编程之ConcurrentHashMap

ConcurrentHashMap ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法.ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁. ConcurrentHashMap的内部结构 ConcurrentHashMap为了提高本身的并发能力,在内部采用了一个叫做Segment

Java并发编程之set集合的线程安全类你知道吗

Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习>系列之<并发集合系列>教程的第二篇: 本文主要内容:Set集合子类底层分别是什么?基于底层为什么set的子类可以存放一个数据?怎么解决set线程安全问题? 一:Set集合子类 Set的三个子类分别是:HaseSet.TreeSet.LinkedHashSet.这三个都是线程不安全的.那么这三个子类

java并发编程之Master-Worker模式

Master-Worker模式适合在一个任务可以拆分成多个小任务来进行的情况下使用. package cn.fcl.masterworker; import java.util.HashMap; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; public c

Java并发编程之volatile的理解

Java并发编程之volatile关键字的理解 Java中每个线程都有自己的工作内存,类比于处理器的缓存,线程的工作内存中保存了被该线程使用到的变量的主内存的拷贝.线程读写变量都是直接在自己的工作内存中进行的,而何时刷新数据(指将修改的结果更新到主存或者把主存的变量读取覆盖掉工作内存中的值)是不确定的. volatile关键字是修饰字段的关键字,貌似是JDK1.5之后才有的,在多线程编程中,很大的几率会用到这个关键字,volatile修饰变量后该变量有这么一种效果:线程每一次读该变量都是直接从主

java并发编程之future模式

1.当你想并发去执行一段代码,但是还想获取这段代码的返回结果,那么future多线程模式就可以派上用场了,代码实现如下. public class Client { public Data request() { final FutureData futureData = new FutureData(); new Thread(new Runnable() { @Override public void run() { futureData.setRealData(new RealData()

java并发编程之Guarded Suspention

当客户端请求速度远远大于服务端的处理速度,这时候就非常适合使用Guarded Suspention模式 package cn.fcl.guardendSuspension; import java.util.ArrayList; import java.util.List; public class RequestQueue { private List<Integer> integers = new ArrayList<Integer>(); public synchronize

Java并发编程之Condition

1.使用synchronized中的等待和唤醒实现消费者和生产者模式 /** * 使用Synchronized实现消费者生产者模式 */ public class SynchronizedDemo { static List<Integer> list = new ArrayList<Integer>(); private static int maxNum = 5; // 消费者 private void Consumer(String name){ synchronized (