java線程併發庫

 

ThreadLocal的使用,,,實際上相當於維護了一個Map,其中以鍵值對的形式,存儲了某一個數據被多個線程訪問所對應的值。當然這個數據只能有一份,可以是List。。可以是對象。。可以是javabean。。。其Map中每一個Entry保存進去的鍵就是當前線程,值就是這個線程所訪問的那份數據。。。。比方說在服務器端單獨起一個獨立線程來實現與某個客戶端交互,,,其中交互過程裏所有涉及到的公共模塊所訪問的都是一份數據,,所以顧名思義被叫做線程範圍內的數據共享。。。。。想象的到在javaEE中的應用是非常多的。。。。

 

 

  1. package localTest;  
  2.   
  3. //import java.util.HashMap;   
  4. //import java.util.Map;   
  5. import java.util.Random;  
  6.   
  7. public class ThreadLocalTest {  
  8.     public static int data;  
  9. //  public static Map dataMap = new HashMap();   
  10. //  public static ThreadLocal dataLocal = new ThreadLocal();   
  11.     public static void main(String[] args) {  
  12.         for (int i = 0; i < 2; i++) {  
  13.             new Thread() {  
  14.                 public void run() {  
  15. //                  ThreadLocalTest.data = new Random().nextInt();   
  16. //                  ThreadLocalTest.dataMap.put(Thread.currentThread().getName(),   
  17. //                          new Random().nextInt());   
  18. //                  ThreadLocalTest.dataLocal.set(new Random().nextInt());   
  19.                     int data = new Random().nextInt();  
  20.                     MyData.getInstance().setData(data);  
  21.                     System.out.println(Thread.currentThread().getName()  
  22.                             + " put data : " + data);  
  23.                     System.out.println(Thread.currentThread().getName()  
  24.                             +" A get data : " + new A().get());  
  25.                     System.out.println(Thread.currentThread().getName()  
  26.                             +" B get data : " + new B().get());  
  27.                 }  
  28.             }.start();  
  29.         }  
  30.     }  
  31.   
  32. }  
  33.   
  34. class A {  
  35.     public int get() {  
  36. //      return (Integer)ThreadLocalTest.dataLocal.get();   
  37.         return MyData.getInstance().getData();  
  38.     }  
  39. }  
  40.   
  41. class B {  
  42.     public int get() {  
  43. //      return (Integer)ThreadLocalTest.dataLocal.get();   
  44.         return MyData.getInstance().getData();  
  45.     }  
  46. }  
  47.   
  48. class MyData{  
  49.     private static ThreadLocal<MyData> myData = new ThreadLocal<MyData>();  
  50.     private int data;  
  51.     public int getData(){  
  52.         return data;  
  53.     }  
  54.     public void setData(int data){  
  55.         this.data = data;  
  56.     }  
  57.     private MyData(){}  
  58.     public static MyData getInstance(){  
  59.         MyData data = myData.get();  
  60.         if(data==null){  
  61.             data = new MyData();  
  62.             myData.set(data);  
  63.         }  
  64.         return data;  
  65.     }  
  66. }  

 

接着是線程併發庫中的java.util.concurrent.atomic包中提供了對一些數據類型的擴展,使得對那些數據類型的操作封裝成爲了方法,而那些方法都是線程安全的,atomic解釋是原子的,,支持在單個變量上解除鎖的線程安全編程。。。。其中包括Integer,boolean以及IntegerArray和引用類型。。

 

 

接下來就是線程池了,,於jdbc數據庫連接池同理,,大大的提高了程序運行的效率。。因爲創建一個新的線程還是很耗資源的。。

我們也只需要用到一個類,,java.util.concurrent包的老大,,,Executors類,,提供一系列靜態方法,用於創建各種線程池,,其中包含固定大小線程,和自動大小線程池(通過任務數量來分配線程數量),以及單一線程池(始終保持有一個線程在池子裏)。。。還有可調度的線程池,相當於定時器。。其中定時器任務代碼內還可嵌套另外的定時器。。。通過調用線程池的shutdown方法在任務執行完畢後殺死池內線程。shutdownNow直接殺死。。interrupt!ALL!!!

 

  1. package concurrent;  
  2.   
  3. import java.util.Random;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6.   
  7. public class ThreadPoolTest {  
  8.     public static void main(String[] args) {  
  9.         ExecutorService pool = Executors.newCachedThreadPool();//Executors.newFixedThreadPool(3);   
  10.         for (int i = 0; i < 10; i++) {  
  11.             final int taskId = i;  
  12.             pool.execute(new Runnable() {  
  13.                 public void run() {  
  14.                     for (int j = 0; j < 10; j++) {  
  15.                         try {  
  16.                             Thread.sleep(new Random().nextInt(1000));  
  17.                         } catch (InterruptedException e) {  
  18.                             e.printStackTrace();  
  19.                         }  
  20.                         System.out.println(Thread.currentThread().getName()  
  21.                                 + " execute task " + taskId +   
  22.                                 " loop for " + j);  
  23.                     }  
  24.                 }  
  25.             });  
  26.         }  
  27.         pool.shutdown();  
  28.     }  
  29. }  
  30.   
  31.   
  32.   
  33.   
  34.   
  35. package concurrent;  
  36.   
  37. import java.util.Calendar;  
  38. import java.util.concurrent.Executors;  
  39. import java.util.concurrent.ScheduledExecutorService;  
  40. import java.util.concurrent.TimeUnit;  
  41.   
  42. public class TimerTaskTest {  
  43.     private static int count;  
  44.     public static void main(String[] args) {  
  45.         System.out.println(Calendar.getInstance().get(Calendar.SECOND));  
  46.         final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);  
  47.         class MyTask implements Runnable{  
  48.             public void run(){  
  49.                 count++;  
  50.                 System.out.println(Calendar.getInstance().get(Calendar.SECOND));  
  51.                 System.out.println("bombing!");  
  52.                 if(count%2==1)  
  53.                     timer.schedule(new MyTask(), 4, TimeUnit.SECONDS);  
  54.                 else  
  55.                     timer.schedule(new MyTask(), 3, TimeUnit.SECONDS);  
  56.             }  
  57.         }  
  58.         timer.schedule(new MyTask(), 2, TimeUnit.SECONDS);  
  59.     }  
  60. }  

 

 

 Callable讓線程能夠擁有返回值,類似於Runnable接口,,需要實現call方法,,Future類接受一個Callable的返回值。。。通過get方法獲取返回值,當沒有數據時,它將會等待,什麼時候有數據什麼時候獲取,通過get方法的重載方法可以設置等待時間。。多個Callable利用CompletionService對象來接收返回值,通過submit來接受提交的任務!!!接受返回值時誰先有數據就提取誰的數據!通過take方法放回一個Future對象再調用get方法獲取數據。

 

 

  1. package concurrent;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.CompletionService;  
  5. import java.util.concurrent.Executor;  
  6. import java.util.concurrent.ExecutorCompletionService;  
  7. import java.util.concurrent.ExecutorService;  
  8. import java.util.concurrent.Executors;  
  9. import java.util.concurrent.Future;  
  10. import java.util.concurrent.TimeUnit;  
  11.   
  12. public class CallableTest {  
  13.     public static void main(String[] args) throws Exception {  
  14.         ExecutorService pool = Executors.newSingleThreadExecutor();  
  15.         Future<String> future = pool.submit(new Callable<String>() {  
  16.             @Override  
  17.             public String call() throws Exception {  
  18.                 // TODO Auto-generated method stub   
  19.                 Thread.sleep(3000);  
  20.                 return "Hello world!";  
  21.             }  
  22.         });  
  23.           
  24.         try {  
  25.             System.out.println(future.get(4,TimeUnit.SECONDS));  
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.         pool.shutdown();  
  30.         submit();  
  31.     }  
  32.     public static void submit() throws Exception{  
  33.         Executor executor = Executors.newCachedThreadPool();  
  34.         CompletionService<Integer> service = new ExecutorCompletionService<Integer>(executor);  
  35.         for(int i=0;i<10;i++){  
  36.             final int sep = i;  
  37.             service.submit(new Callable<Integer>() {  
  38.                 public Integer call() throws Exception {  
  39.                     Thread.sleep((int)(Math.random()*1000));  
  40.                     return sep;  
  41.                 }  
  42.             });  
  43.         }  
  44.         for(int i=0;i<10;i++){  
  45.             System.out.println(service.take().get());  
  46.         }  
  47.     }  
  48. }  

 

 

lock,,,普通鎖,,以及讀寫鎖,,可以實現讀與寫之間互斥,讀於讀之間可以並行,寫於寫之間也互斥!!

面試題一道,,通過讀寫鎖編寫一個緩存類得實際應用

 

  1. package concurrent;  
  2.   
  3. import java.util.*;  
  4. import java.util.concurrent.locks.ReadWriteLock;  
  5. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  6.   
  7. public class CacheClass {  
  8.     public static void main(String[] args) {  
  9.         //test();   
  10.     }  
  11.     private ReadWriteLock rwl = new ReentrantReadWriteLock();  
  12.     private Map<String,Object> cacheData = new HashMap<String,Object>();  
  13.     public Object get(String key){  
  14.         rwl.readLock().lock();  
  15.         Object obj = null;  
  16.         try {  
  17.             obj = cacheData.get(key);  
  18.             if(obj==null){  
  19.                 rwl.readLock().unlock();  
  20.                 rwl.writeLock().lock();  
  21.                 obj = "Shawn";//readDatabase();   
  22.                 cacheData.put(key, obj);  
  23.                 rwl.writeLock().unlock();  
  24.                 rwl.readLock().lock();  
  25.             }  
  26.         } finally {  
  27.             rwl.readLock().unlock();  
  28.         }  
  29.           
  30.         return obj;  
  31.     }  
  32. }  

 

 

以及通過面向對象設計的一另一道面試題,,子線程執行5次,主線程執行10次,這樣循環總共10次。。。通過synchronized關鍵字修飾子線程和主線程需要執行的方法封裝到一個類當中,通過一個boolean變量來標識子線程和主線程的執行次序。。。然後各自循環10次。。。同樣實現兩個子線程和一個主線程來交替執行,這個時候就需要用到顯示鎖,通過多個條件變量(condition)來實現,,線程1獲得鎖,執行完釋放並通知條件變量2,線程2獲得鎖,執行完釋放並通知條件變量3,以此類推,,4個或5個線程交替執行也同理!!!

 

  1. package concurrent;  
  2.   
  3. public class InterViewSubject {  
  4.     public static void main(String[] args) {  
  5.         init();  
  6.     }  
  7.   
  8.     private static void init() {  
  9.         final MyData data = new MyData();  
  10.         new Thread() {  
  11.             public void run() {  
  12.                 for (int i = 0; i < 10; i++) {  
  13.                     data.sub();  
  14.                 }  
  15.             }  
  16.         }.start();  
  17.         for (int i = 0; i < 10; i++) {  
  18.             data.main();  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. class MyData {  
  24.     private boolean isMain;  
  25.   
  26.     public synchronized void sub() {  
  27.         if (!isMain) {  
  28.             for (int i = 0; i < 5; i++) {  
  29.                 System.out.println("sub Thread loop for : " + i);  
  30.             }  
  31.         } else  
  32.             try {  
  33.                 this.wait();  
  34.             } catch (InterruptedException e) {  
  35.                 e.printStackTrace();  
  36.             }  
  37.         isMain = true;  
  38.         this.notify();  
  39.     }  
  40.   
  41.     public synchronized void main() {  
  42.         if (isMain) {  
  43.             for (int i = 0; i < 10; i++) {  
  44.                 System.out.println("main Thread loop for : " + i);  
  45.             }  
  46.         } else  
  47.             try {  
  48.                 this.wait();  
  49.             } catch (InterruptedException e) {  
  50.                 e.printStackTrace();  
  51.             }  
  52.         isMain = false;  
  53.         this.notify();  
  54.     }  
  55. }  

 

 

 

  歡迎大家評論,,大家能夠討論討論咱們所學的知識點有些什麼實際應用場景!!!這也是我們最終學習新知識的最終目的!!!

 

出自:http://blog.csdn.net/a15874647/article/details/6440998

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