多線程及線程並發庫

來源:互聯網
上載者:User

1. 建立和啟動線程的兩種傳統方式

概念:java 實現一條線索
有兩種方法:
1、繼承thread 類
例子:
// 繼承Thread類

 new Thread(){        publicvoid run(){          while(true){             try {                Thread.sleep(2000);             }catch (InterruptedException e) {                e.printStackTrace();             }   System.out.println(Thread.currentThread().getName());          }        }      }.start();  

2、實現runnable介面
例子:

//實現Runnable介面      new Thread(new Runnable(){        publicvoid run(){          while(true){             try {                Thread.sleep(2000);             }catch (InterruptedException e) {                e.printStackTrace();             }          System.out.println(Thread.currentThread().getName());          }        }      }).start();

2.傳統的定時器實現方式
代碼

importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;publicclass TimerTest {   /**    * 定時器    */   publicstaticvoid main(String[] args) {      ScheduledExecutorServiceservice =  Executors.newScheduledThreadPool(3);      service.scheduleAtFixedRate(          new Runnable(){             publicvoid run() {                System.out.println(Thread.currentThread().getName());             }          },          10,          1,          TimeUnit.SECONDS);      while(true){        try {          Thread.sleep(2000);        } catch (InterruptedException e) {          e.printStackTrace();        }        System.out.println(Thread.currentThread().getName());      }   }}

3.傳統的線程同步互斥

 線程的同步和互斥   Synchronized線程建立過程:同步:子線程迴圈10次,接著主線程迴圈100次,接著的又回到子線程迴圈10次,接著又回到主線程迴圈10次。如此,迴圈50次。
packageorg.nagi.Thread;publicclass TeaTSynchronized {   static Businessbusiness =new Business();   publicstaticvoid main(String[] args)throws InterruptedException {      //子線程      TeaTSynchronized.init();      //主線程      for(int i=0;i<50;i++){        business.main();      }   }   //子線程   publicstaticvoid init(){        new Thread(new Runnable() {          @Override          publicvoid run() {             for(int i=0;i<50;i++){                 try {                   business.sub();                }catch (InterruptedException e) {                   e.printStackTrace();                }             }          }        }).start();   }}
 class Business{    booleanshouldSub =true;    //子線程方法    publicsynchronizedvoid sub()throws InterruptedException{      //使用我當前線程的,等待       while(!shouldSub){//這裡使用while而不用iF防止假喚醒。詳細資料可參考JavaApi         this.wait();            }       for(int i=0;i<10;i++){         System.out.println(Thread.currentThread().getName()+"count" + i);       }       shouldSub = false;       this.notify();    }    //主線程的操作方法    publicsynchronizedvoid main()throws InterruptedException{       while(shouldSub){//這裡使用while而不用iF防止假喚醒。詳細資料可參考JavaApi         //使用我當前線程的,等待         this.wait();       }       for(int i=0;i<100;i++){         System.out.println(Thread.currentThread().getName()+"count" + i);       }       shouldSub = true;       this.notify();    }}

4.傳統的線程間通訊

 ThreadLoacal 線程間的通訊:就是線程內的資料共用,兩個或多個代碼塊共用的一個資料, 在代碼塊之間資料是獨立,在代碼塊之內是資料共用的。

5.ThreadLocal與線程級變數共用

   ThreadLoacal就相當Map; 一個線程TheadLoacal 只能放一個資料;

6.多線程訪問共用資料的經典總結

   1、可以把需要共用的資料轉給runnable 介面;   2、將共用資料的封裝為一個對象, 在多個線程裡面runnable 介面run方法   3、可以使用ThreadLocal類

如果想要操作一個原子性的資料類型可以用原子方式更新的 int 值。
在操作某一個資料原子性操作的時候,可以使用AtomicInteger AtomicIntegerArray

 定義一個線程池:
packageorg.nagi.Thread;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;/** *線程池 *@author dell * */publicclass ThreadPool {   publicstaticvoid main(String[] args) {      /*緩衝線程池*/      //ExecutorService  threadcached=Executors.newCachedThreadPool();      /*單個線程池,當線程死了,自動會有線程啟動*/      //ExecutorService threadSingle = Executors.newSingleThreadScheduledExecutor();      //線程池      ExecutorService  threadPool = Executors.newFixedThreadPool(4);        threadPool.execute(new Runnable() {          @Override          publicvoid run() {             for(int i=0;i<5;i++){                System.out.println(Thread.currentThread().getName()+"任務:"+ i);             }          }        });        //當任務執行完成之後就可以關閉掉        threadPool.shutdown();   }}

8.Java5中的定時器

方法參考
ScheduledFuture
schedule(Callable callable, long delay, TimeUnit unit)
建立並執行在給定延遲後啟用的 ScheduledFuture。
ScheduledFuture

   Executors.newScheduledThreadPool(4).scheduleAtFixedRate(             new Runnable() {                @Override                publicvoid run() {                   System.out.println("Bombing");                }             },             4,//多少秒之後執行run方法             2,//間隔多少時間執行              TimeUnit.SECONDS);//時間單位Callable和Futrue使用:        /*使用Callable調用回返一個資料,使用futrue去取並且可以指定時間*/        ExecutorService  threadSingle = Executors.newSingleThreadExecutor();        Future<String> futrue =threadSingle.submit(newCallable<String>() {          @Override          public String call()throws Exception {             Thread.sleep(1000);             return"hello world";          }        });        try {          //futrue取出資料          System.out.println("result:" + futrue.get(3,TimeUnit.SECONDS));        } catch (Exceptione) {          e.printStackTrace();        }

9.java5提供的可返回結果的線程模式

10.java5中的鎖與讀寫鎖

Lock:java 中鎖Lock 比Synchronized更加的面對對象,與生活中的對象一樣,鎖業是一個對象。
例子代碼:

importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclass LockTest {   /**    * @param args    */   publicstaticvoid main(String[] args) {      final Business business =new Business();      ExecutorService service = Executors.newFixedThreadPool(3);      for(int i=0;i<3;i++){        service.execute(new Runnable(){          publicvoid run(){             business.service();          }        });      }      service.shutdown();   }}class Business{   privateintcount = 0;   Lock lock = new ReentrantLock();   publicvoid service(){      lock.lock();      count++;      try {        Thread.sleep(10);        System.out.println(count);          } catch (InterruptedException e) {        e.printStackTrace();      }finally{        lock.unlock();      }   }}Lock : 還可以實現一個讀寫鎖,/**    * 讀的的時候不互斥    * 寫的時候互斥    * @param key    * @return    */   public Object getEntityFromCache(Stringkey){      Object object = cache.get(key);      if(object ==null){        lock.readLock().lock();//鎖得read操作        try{          object ="btbu";//去資料庫尋找          cache.put(key, object);        }finally{          lock.readLock().unlock();        }      }      return object;   }

11.LockCondition同步工具

Condition 將 Object 監視器方法(wait、notify和notifyAll)分解成截然不同的對象,以便通過將這些對象與任意Lock 實現組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。

例子:

packageorg.nagi.Thread;import java.util.concurrent.locks.Condition;importjava.util.concurrent.locks.ReentrantLock;publicclass TestCondition {   static Businessbusiness =new Business();   publicstaticvoid main(String[] args)throws InterruptedException {      //子線程      TestCondition.init();      //主線程      for(int i=0;i<50;i++){        business.main();      }   }   //子線程   publicstaticvoid init(){        new Thread(new Runnable() {          @Override          publicvoid run() {             for(int i=0;i<50;i++){                 try {                   business.sub();                }catch (InterruptedException e) {                   e.printStackTrace();                }             }          }        }).start();   }}
 class Business{    booleanshouldSub =true;    ReentrantLock lock = new ReentrantLock();    Condition condition =lock.newCondition();    //子線程方法    public void sub()throws InterruptedException{       lock.lock();       try{          //使用我當前線程的,等待           while(!shouldSub){//這裡使用while而不用iF防止假喚醒。詳細資料可參考JavaApi               condition.await();                }           for(int i=0;i<10;i++){              System.out.println(Thread.currentThread().getName()+"count" + i);           }           shouldSub =false;       }finally{         condition.signal();       }    }    //主線程的操作方法    publicsynchronizedvoid main()throws InterruptedException{       lock.lock();       try{         while(shouldSub){//這裡使用while而不用iF防止假喚醒。詳細資料可參考JavaApi           //使用我當前線程的,等待           condition.await();         }         for(int i=0;i<100;i++){           System.out.println(Thread.currentThread().getName()+"count" + i);         }         shouldSub = true;         this.notify();       }finally{         condition.signal();       }    }}

緩衝隊列的實現

import java.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/** *緩衝隊列 *@author dell * */class BoundedBuffer{   final Locklock =new ReentrantLock();   final ConditionnotFull =lock.newCondition();   final ConditionnotEmpty =lock.newCondition();   //一個數組的緩衝區   final Object[]items =new Object[100];   intputptr,takeptr,count;   //存放的操作   publicvoid put(Object x)throws InterruptedException {     lock.lock();     try {       while (count ==items.length)         notFull.await();       items[putptr] = x;       if (++putptr ==items.length)putptr = 0;       ++count;       notEmpty.signal();     } finally {       lock.unlock();     }   }   //取出資料的操作   public Object take()throwsInterruptedException {     lock.lock();     try {       while (count == 0)         notEmpty.await();       Object x = items[takeptr];       if (++takeptr ==items.length)takeptr = 0;       --count;       notFull.signal();       return x;     } finally {       lock.unlock();     }   } }

12.Semaphore同步工具

代碼:

importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Semaphore;/** *號誌 *@author dell * */publicclass SemaphoreTest {   publicstaticvoid main(String[] args) {      //緩衝串連池      ExecutorService service = Executors.newCachedThreadPool();      final Semaphore sp =new Semaphore(3);      for(int i=0;i<10;i++){        Runnable runnable = new Runnable(){             publicvoid run(){             try {                sp.acquire();//獲得訊號量許可             }catch (InterruptedException e1) {                e1.printStackTrace();             }             System.out.println("線程" + Thread.currentThread().getName() +                   "進入,當前已有" + (3-sp.availablePermits()) +"個並發");             try {                Thread.sleep((long)(Math.random()*10000));             }catch (InterruptedException e) {                e.printStackTrace();             }             System.out.println("線程" + Thread.currentThread().getName() +                   "即將離開");                           sp.release();//釋放訊號量             //下面代碼有時候執行不準確,因為其沒有和上面的代碼合成原子單元             System.out.println("線程" + Thread.currentThread().getName() +                   "已離開,當前已有" + (3-sp.availablePermits()) +"個並發");                       }        };        //執行已提交的 Runnable任務的對象。        service.execute(runnable);          }   }}

運行結果:
線程pool-1-thread-1進入,當前已有1個並發
線程pool-1-thread-1即將離開
線程pool-1-thread-1已離開,當前已有0個並發
線程pool-1-thread-2進入,當前已有1個並發
線程pool-1-thread-2即將離開
線程pool-1-thread-2已離開,當前已有0個並發
線程pool-1-thread-3進入,當前已有1個並發
線程pool-1-thread-3即將離開

13.CyclicBarrier同步工具

一個同步輔助類,它允許一組線程互相等待,直到到達某個公用屏障點 (common barrier point)。在涉及一組固定大小的線程的程式中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程後可以重用,所以稱它為迴圈的 barrier。

代碼:

import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** *並發工具輔佐類 * *之迴圈障礙點 *@author dell * */publicclass CyclicBarrierTest {   publicstaticvoid main(String[] args) {      ExecutorService service = Executors.newCachedThreadPool();      final CyclicBarrier cb =newCyclicBarrier(3);      for(int i=0;i<3;i++){        Runnable runnable = new Runnable(){             publicvoid run(){             try {                Thread.sleep((long)(Math.random()*10000));                 System.out.println("線程" + Thread.currentThread().getName() +                     "即將到達集合地點1,當前已有" + cb.getNumberWaiting() +"個已經到達,正在等候");                               cb.await();                Thread.sleep((long)(Math.random()*10000));                 System.out.println("線程" + Thread.currentThread().getName() +                     "即將到達集合地點2,當前已有" + cb.getNumberWaiting() +"個已經到達,正在等候");                               cb.await();                Thread.sleep((long)(Math.random()*10000));                 System.out.println("線程" + Thread.currentThread().getName() +                     "即將到達集合地點3,當前已有" + cb.getNumberWaiting() +"個已經到達,正在等候");                               cb.await();                          }catch (Exception e) {                e.printStackTrace();             }                   }        };        service.execute(runnable);      }      service.shutdown();   }}

14.CountDownLatch同步工具

一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。首先先是點時器,
用給定的計數 初始化 CountDownLatch。由於調用了countDown()方法,所以在當前計數到達零之前,await方法會一直受阻塞。之後,會釋放所有等待的線程,await的所有後續調用都將立即返回。這種現象只出現一次——計數無法被重設。

importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;/** *程式計數器 *@author dell * */publicclass CountdownLatchTest {   publicstaticvoid main(String[] args) {      ExecutorService service = Executors.newCachedThreadPool();      //命令      final CountDownLatch cdOrder =new CountDownLatch(1);      //需要3個都為了時候再執行      final CountDownLatch cdAnswer =new CountDownLatch(3);          for(int i=0;i<3;i++){        Runnable runnable = new Runnable(){             publicvoid run(){              try {               System.out.println("線程" + Thread.currentThread().getName() +                     "正準備接受命令");                               cdOrder.await();               System.out.println("線程" + Thread.currentThread().getName() +                "已接受命令");                                   Thread.sleep((long)(Math.random()*10000));                 System.out.println("線程" + Thread.currentThread().getName() +                     "回應命令處理結果");                //減1,當計數器為0的時候,再可以往下執行                cdAnswer.countDown();                           }catch (Exception

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.