Java ThreadLocal
2016-03-26 11:14
645 查看
ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本。也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本,从而避免并发线程同时读写同一个变量资源时的冲突。
示例如下:
运行结果:
由运行结果可知,各线程都用于各自的Local变量,并各自读写互不干扰。
ThreadLocal共提供了三个方法来操作,set,get和remove。
在Android 中的Looper,即使用了ThreadLocal来为每个线程都创建各自独立的Looper对象。
当某个线程需要自己的Looper及消息队列时,就调用Looper.prepare(),它会为线程创建属于线程的Looper对象及MessageQueue,并将Looper对象保存在ThreadLocal中。
示例如下:
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import com.sun.javafx.webkit.Accessor; public class ThreadLocalTest { static class ThreadLocalVariableHolder { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() { private Random random = new Random(); protected synchronized Integer initialValue() { return random.nextInt(10000); } }; public static void increment() { value.set(value.get() + 1); } public static int get() { return value.get(); } } static class Accessor implements Runnable{ private final int id; public Accessor(int id) { this.id = id; } @Override public void run() { while (!Thread.currentThread().isInterrupted()) { ThreadLocalVariableHolder.increment(); System.out.println(this); Thread.yield(); } } @Override public String toString() { return "#" + id + ": " + ThreadLocalVariableHolder.get(); } } public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { executorService.execute(new Accessor(i)); } try { TimeUnit.MICROSECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } executorService.shutdownNow(); } }
运行结果:
#1: 9685 #1: 9686 #2: 138 #2: 139 #2: 140 #2: 141 #0: 5255 。。。
由运行结果可知,各线程都用于各自的Local变量,并各自读写互不干扰。
ThreadLocal共提供了三个方法来操作,set,get和remove。
在Android 中的Looper,即使用了ThreadLocal来为每个线程都创建各自独立的Looper对象。
public final class Looper { private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } 。。。 }
当某个线程需要自己的Looper及消息队列时,就调用Looper.prepare(),它会为线程创建属于线程的Looper对象及MessageQueue,并将Looper对象保存在ThreadLocal中。
相关文章推荐
- 去除MyEclipse 中新建servlet多余的注释问题
- 简单谈谈java的异常处理(Try Catch Finally)
- Eclipse安装svn的过程记录
- Java 二叉查找树转化为排序的循环双链表
- spring Resolving views
- JAVA Class String
- 二、Java学习之语言基础(1)
- zookeeper错误记录一;Cannot open channel to 2 at election address s1/192.168.253.131:3888 java.net.Connec
- Spring 注解详解
- 【字符编码】Java字符编码详细解答及问题探讨
- 判断java中两个对象是否相等
- 接口与内部类(Java核心技术卷Ⅰ)
- 编译OpenJDK记录
- Java总结篇系列:Java泛型
- Java 封装 HDFS API 操作
- Java使用基本字节流OutputStream的四种方式对于数据复制(文本,音视频,图像等数据)
- java中IO流操作的标准异常类
- eclipse通过jdbc访问mysql数据库
- java关键字总结
- ZooKeeper Java API简单示例