多线程共享数据

来源:互联网 发布:php记账系统源码 编辑:程序博客网 时间:2024/06/05 15:08

线程范围的共享数据包括线程范围内共享和线程间共享数据

  • 线程范围内共享数据
线程范围内共享数据有两种方式:自定义一个Map<Thread, Object>用来保存线程的数据或者是用ThreadLocal类。
使用Map<Thread, Object>
package traditional;import java.util.HashMap;import java.util.Map;import java.util.Random;public class ThreadScopeShareData {private static Map<Thread,Integer> threadMap = new HashMap<Thread,Integer>();public static void main(String[] args) {for(int i = 0 ; i < 2; i++){//开启两个线程new Thread(new Runnable(){@Overridepublic void run() {int data = new Random().nextInt();System.out.println(Thread.currentThread().getName()+" has put data : "+data);threadMap.put(Thread.currentThread(), data);new A().get();new B().get();}}).start();}}static class A{public void get(){int data = threadMap.get(Thread.currentThread());System.out.println("A from "+ Thread.currentThread().getName()+"has put data : "+ data);}}static class B{public void get(){int data = threadMap.get(Thread.currentThread());System.out.println("B from "+ Thread.currentThread().getName()+"has put data : "+ data);}}}

使用ThreadLocal类
package traditional;import java.util.Random;/** * ThreadLocal实现线程范围的共享变量 */public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();// private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();//不要这样做public static void main(String[] args) {for (int i = 0; i < 2; i++) {// 开启两个线程new Thread(new Runnable() {@Overridepublic void run() {int data = new Random().nextInt();System.out.println(Thread.currentThread().getName() + " has put data : " + data);threadLocal.set(data);// 把data数据存储到当前线程/* * MyThreadScopeData myData = new MyThreadScopeData(); * myData.setName("name"+data); myData.setAge(data); * myThreadScopeData.set(myData); */MyThreadScopeData.getThreadInstance().setName("name" + data);MyThreadScopeData.getThreadInstance().setAge(data);new A().get();new B().get();}}).start();}}static class A {public void get() {int data = threadLocal.get();// 取到当前线程的data值System.out.println("A from " + Thread.currentThread().getName() + " has put data : " + data);MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();System.out.println("A from " + Thread.currentThread().getName() + " get myData : " + myData.getName() + ", "+ myData.getAge());}}static class B {public void get() {int data = threadLocal.get();// 取到当前线程的data值System.out.println("B from " + Thread.currentThread().getName() + " has put data : " + data);MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();System.out.println("B from " + Thread.currentThread().getName() + " get myData : " + myData.getName() + ", "+ myData.getAge());}}}/** * 把ThreadLocal放到封装的类中 *  * 专门与线程绑定 在线程的任何地方调用该类的instance,就会产生与当前线程有关的实例 * */class MyThreadScopeData {// 类似于单例设计模式private MyThreadScopeData() {}public /* synchronized */ static MyThreadScopeData getThreadInstance() {MyThreadScopeData instance = map.get();if (instance == null) {instance = new MyThreadScopeData();map.set(instance);}return instance;}// private static MyThreadScopeData instance = null;private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();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;}}
  • 线程之间共享数据
1、如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如买票系统就可以这么做。
2、如果每个线程执行的代码不相同,这时候就需要用不同的Runnable对象
2.1、把共享变量封装在一个对象中,然后把这个对象逐一传递给各个Runnable对象。(可以写自己的Runnable,然后以构造函数的方式传递共享变量进去)
// 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。package traditional; public class MultiThreadShareData {      public static void main(String[] args) {           final ShareData1 data1 = new ShareData1();      new Thread(new Runnable(){         @Override         public void run() {            data1.decrement();         }      }).start();           new Thread(new Runnable(){         @Override         public void run() {            data1.increment();         }      }).start();   }  }class ShareData1{     private int j = 0;   public synchronized void increment(){      j++;   }     public synchronized void decrement(){      j--;   }  } 内部类可以访问外部类的成员变量另外的方法:package traditional; public class ThreadTest1 {   private int j;    public static void main(String args[]) {      ThreadTest1 tt = new ThreadTest1();      Inc inc = tt.new Inc();      Dec dec = tt.new Dec();      for (int i = 0; i < 2; i++) {         Thread t = new Thread(inc);         t.start();         t = new Thread(dec);         t.start();      }   }    private synchronized void inc() {      j++;      System.out.println(Thread.currentThread().getName() + "-inc:" + j);   }    private synchronized void dec() {      j--;      System.out.println(Thread.currentThread().getName() + "-dec:" + j);   }    class Inc implements Runnable {      public void run() {         for (int i = 0; i < 100; i++) {            inc();         }      }   }    class Dec implements Runnable {      public void run() {         for (int i = 0; i < 100; i++) {            dec();         }      }   }



原创粉丝点击