ThreadLocal实现线程范围内共享变量

来源:互联网 发布:unity3d引擎架构设计 编辑:程序博客网 时间:2024/06/05 14:20

 1.多线程范围内访问共享对象和数据的方式。

 1).如果每个线程要执行的代码一样,可以使用同一个Runnable对象,这个Runnable对象中有共享数据,例如:买票系统。

 2).每一个线程要执行的代码不一样,这样就需要使用多个Runnable对象了。有以下几种方式:

 (1).将需要共享的数据单独封装在一个对象中,创建该对象的实例逐一传递给Runnable对象。

  

<span style="font-size:18px;"><span style="font-size:24px;"> final ShareData data =new ShareData();new Thread(new Runnable(){@Overridepublic void run() {while(true){data.increment();}}}).start();new Thread(new Runnable(){@Overridepublic void run() {while(true){data.decrement();}}}).start();}}class ShareData{private int j ;public synchronized void increment(){j++;System.out.println(Thread.currentThread().getName()+ " increment "+j);}public synchronized void decrement(){j--;System.out.println(Thread.currentThread().getName()+ " decrement "+j);}}</span></span>
  (2).将需要共享的数据封装在Runnable对象中。

<span style="font-size:18px;"><span style="font-size:24px;">class Runnable1 implements Runnable{@Overridepublic void run() {//...}}class Runnable2 implements Runnable{@Overridepublic void run() {//...}}</span></span>

 (3).将Runnable对象作为某一个类的内部类, 共享数据作为这个类的外部类。

 2).极端的一种方式,即在任意一个类中定义一个static变量,这将被所有线程共享。

 2.线程范围内的共享数据。

   对于同一份程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外一个线程运行时又共享另外一份数据。
  

 自已来做的话,也很好做。

<span style="font-size:18px;"><span style="font-size:24px;">package com.hb;import java.util.HashMap;import java.util.Map;import java.util.Random;public class ThreadLocal {private final static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>();public static void main(String[] args) {// 创建三个线程,并且生产三个数据for (int i = 0; i < 3; i++) {new Thread(new Runnable() {@Overridepublic void run() {int data = new Random().nextInt();threadData.put(Thread.currentThread(), data);System.out.println(Thread.currentThread().getName()+ " has put data " + data);new A().get();new B().get();}}).start();}}// 模块Astatic class A {int data = threadData.get(Thread.currentThread());public void get() {System.out.println("A from " + Thread.currentThread().getName()+ " get data " + data);}}// 模块Bstatic class B {int data = threadData.get(Thread.currentThread());public void get() {System.out.println("B from " + Thread.currentThread().getName()+ " get data " + data);}}}</span></span>

java对这个threadData进行了封装,ThreadLocal相当于一个Map,每一个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map增加一条记录。key分别是各自的线程。

<span style="font-size:18px;">package com.hb;import java.util.HashMap;import java.util.Map;import java.util.Random;public class ThreadLocalTest {//private final static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>(); private final static ThreadLocal<Integer> threadData=new ThreadLocal();public static void main(String[] args) {// 创建三个线程,并且生产三个数据for (int i = 0; i < 3; i++) {new Thread(new Runnable() {@Overridepublic void run() {int data = new Random().nextInt();//threadData.put(Thread.currentThread(), data);threadData.set(data);System.out.println(Thread.currentThread().getName()+ " has put data " + data);new A().get();new B().get();}}).start();}}// 模块Astatic class A {int data = threadData.get();//threadData.get(Thread.currentThread());public void get() {System.out.println("A from " + Thread.currentThread().getName()+ " get data " + data);}}// 模块Bstatic class B {int data = threadData.get();//threadData.get(Thread.currentThread());public void get() {System.out.println("B from " + Thread.currentThread().getName()+ " get data " + data);}}}</span>

值得注意的是一个ThreadLocal代表一个变量,故其中只能放一个数据。那我想放多个怎么办?打包呗。

l实现对ThreadLocal变量的封装,让外界不要直接操作ThreadLocal变量。
对基本类型的数据的封装,这种应用相对很少见。
对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。

<span style="font-size:18px;">package com.hb;import java.util.Random;import com.hb.ThreadLocalTest.A;import com.hb.ThreadLocalTest.B;public class ThreadLocalTest2 {public static void main(String[] args) {// 创建三个线程,并且生产三个数据for (int i = 0; i < 3; i++) {new Thread(new Runnable() {@Overridepublic void run() {int data = new Random().nextInt(); MyThreadScopeData.getThreadInstance().setName("name"+data); MyThreadScopeData.getThreadInstance().setAge(data);System.out.println(Thread.currentThread().getName()+ " has put data " + data);new A().get();new B().get();}}).start();}}static class A{public void get(){MyThreadScopeData myData =MyThreadScopeData.getThreadInstance();System.out.println("A from "+Thread.currentThread().getName()+ " get  name "+myData.getName()+", get age "+myData.getAge());}}static class B{public void get(){MyThreadScopeData myData =MyThreadScopeData.getThreadInstance();System.out.println("B from "+Thread.currentThread().getName()+ " get  name "+myData.getName()+", get age "+myData.getAge());}}}class MyThreadScopeData{//将ThreadLocal封装在此。private MyThreadScopeData(){}private static ThreadLocal<MyThreadScopeData> maps=new ThreadLocal<MyThreadScopeData>();public static MyThreadScopeData getThreadInstance(){MyThreadScopeDatainstance =maps.get();if(instance == null){instance =new MyThreadScopeData();maps.set(instance);}return instance;}private String name;private int age;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;}}</span>




0 0
原创粉丝点击