多線程共享數據

線程範圍的共享數據包括線程範圍內共享和線程間共享數據

  • 線程範圍內共享數據
線程範圍內共享數據有兩種方式:自定義一個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(){
				@Override
				public 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() {
				@Override
				public 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();
         }
      }
   }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章