熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

高級應用 java多線程設計模式詳解之一

2022-06-13   來源: Java高級技術 

  線程的創建和啟動
  
  java語言已經內置了多線程支持所有實現Runnable接口的類都可被啟動一個新線程新線程會執行該實例的run()方法當run()方法執行完畢後線程就結束了一旦一個線程執行完畢這個實例就不能再重新啟動只能重新生成一個新實例再啟動一個新線程
  
  Thread類是實現了Runnable接口的一個實例它代表一個線程的實例並且啟動線程的唯一方法就是通過Thread類的start()實例方法
  
  Thread t = new Thread();
  tstart();
  
  start()方法是一個native方法它將啟動一個新線程並執行run()方法Thread類默認的run()方法什麼也不做就退出了注意直接調用run()方法並不會啟動一個新線程它和調用一個普通的java方法沒有什麼區別
  
  因此有兩個方法可以實現自己的線程
  
  方法自己的類extend Thread並復寫run()方法就可以啟動新線程並執行自己定義的run()方法例如
  
  public class MyThread extends Thread {
  public run() {
  Systemoutprintln(MyThreadrun());
  }
  }
  
  在合適的地方啟動線程new MyThread()start();
  
  方法如果自己的類已經extends另一個類就無法直接extends Thread此時必須實現一個Runnable接口
  
  public class MyThread extends OtherClass implements Runnable {
  public run() {
  Systemoutprintln(MyThreadrun());
  }
  }
  
  為了啟動MyThread需要首先實例化一個Thread並傳入自己的MyThread實例
  
  MyThread myt = new MyThread();
  Thread t = new Thread(myt);
  tstart();
  
  事實上當傳入一個Runnable target參數給Thread後Thread的run()方法就會調用targetrun()參考JDK源代碼
  
  public void run() {
  if (target != null) {
  targetrun();
  }
  }
  
  線程還有一些Name ThreadGroup isDaemon等設置由於和線程設計模式關聯很少這裡就不多說了
  
  線程同步
  
  由於同一進程內的多個線程共享內存空間在Java中就是共享實例當多個線程試圖同時修改某個實例的內容時就會造成沖突因此線程必須實現共享互斥使多線程同步
  
  最簡單的同步是將一個方法標記為synchronized對同一個實例來說任一時刻只能有一個synchronized方法在執行當一個方法正在執行某個synchronized方法時其他線程如果想要執行這個實例的任意一個synchronized方法都必須等待當前執行synchronized方法的線程退出此方法後才能依次執行
  
  但是非synchronized方法不受影響不管當前有沒有執行synchronized方法非synchronized方法都可以被多個線程同時執行
  
  此外必須注意只有同一實例的synchronized方法同一時間只能被一個線程執行不同實例的synchronized方法是可以並發的例如class A定義了synchronized方法sync()則不同實例async()和async()可以同時由兩個線程來執行
  
  Java鎖機制
  
  多線程同步的實現最終依賴鎖機制我們可以想象某一共享資源是一間屋子每個人都是一個線程當A希望進入房間時他必須獲得門鎖一旦A獲得門鎖他進去後就立刻將門鎖上於是BCD就不得不在門外等待直到A釋放鎖出來後BCD中的某一人搶到了該鎖(具體搶法依賴於JVM的實現可以先到先得也可以隨機挑選)然後進屋又將門鎖上這樣任一時刻最多有一人在屋內(使用共享資源)
  
  Java語言規范內置了對多線程的支持對於Java程序來說每一個對象實例都有一把一旦某個線程獲得了該鎖別的線程如果希望獲得該鎖只能等待這個線程釋放鎖之後獲得鎖的方法只有一個就是synchronized關鍵字例如
  
  public class SharedResource {
  private int count = ;
  
  public int getCount() { return count; }
  
  public synchronized void setCount(int count) { unt = count; }
  
  }
  
  同步方法public synchronized void setCount(int count) { unt = count; } 事實上相當於
  
  public void setCount(int count) {
  synchronized(this) { // 在此獲得this鎖
  unt = count;
  } // 在此釋放this鎖
  }
  
  紅色部分表示需要同步的代碼段該區域為危險區域如果兩個以上的線程同時執行會引發沖突因此要更改SharedResource的內部狀態必須先獲得SharedResource實例的鎖
  
  退出synchronized塊時線程擁有的鎖自動釋放於是別的線程又可以獲取該鎖了
  
  為了提高性能不一定要鎖定this例如SharedResource有兩個獨立變化的變量
  
  public class SharedResouce {
  private int a = ;
  private int b = ;
  
  public synchronized void setA(int a) { thisa = a; }
  
  public synchronized void setB(int b) { thisb = b; }
  }
  
  若同步整個方法則setA()的時候無法setB()setB()時無法setA()為了提高性能可以使用不同對象的鎖
  
  public class SharedResouce {
  private int a = ;
  private int b = ;
  private Object sync_a = new Object();
  private Object sync_b = new Object();
  
  public void setA(int a) {
  synchronized(sync_a) {
  thisa = a;
  }
  }
  
  public synchronized void setB(int b) {
  synchronized(sync_b) {
  thisb = b;
  }
  }
  }
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27460.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.