首頁 >Java >java教程 >Java開發之多執行緒實作與執行緒安全

Java開發之多執行緒實作與執行緒安全

无忌哥哥
无忌哥哥原創
2018-07-23 09:36:301863瀏覽

多執行緒的實作方式

● 繼承Thread類別建立執行緒類,重寫run方法,run方法就是代表執行緒需要完成的任務,調用線程物件的start()來啟動該線程,線程類別已經繼承了Thread類,所以不能再繼承其他父類。

class ThreadTest extends Thread {  

    Thread thread;  

    public ThreadTest(Thread thread) {  
      this.thread = thread;  
  }  

   @Override  
   public void run() {  
      synchronized (thread) {  
          System.out.println("getObjectLock");  
         try {  
             Thread.sleep(9000);  
       } catch (InterruptedException ex) {  
          ex.printStackTrace();  
         }  
           System.out.println("ReleaseObjectLock");  
    }  
   }  
 }

●  實作Runnable介面建立執行緒類,定義Runnable實作類,重寫run方法

  class RunnableImpl implements Runnable {  
    
     public void run() {  
          try {  
             System.out.println("Begin sleep");  
             Thread.sleep(2000);  
             System.out.println("End sleep");  
          } catch (InterruptedException e) {  
              e.printStackTrace();  
          }  
      }  
   }

● 實作Callable接口,重寫call()方法,call()作為執行緒的執行體,具有返回值

● 線程池,使用線程池產生線程物件java.util.concurrent.ExecutorService、java.util.concurrent.Executors;

#Java如何實現線程安全

● 互斥同步:推薦使用synchronized 關鍵字進行同步, 在concurrent包中有ReentrantLock類, 實現效果差不多. 還是推薦原生態的synchronized.
● 非阻塞同步:需要硬體指令完成.常用的指令有: Test-and-Set Fetch-and-Increment Swap Compare-and-Swap (CAS) Load-Linked/Store-Conditional (LL/SC) 典型的應用在AtomicInteger 中 
 ● 無同步方案:將變數保存在本地執行緒中,就不會出現多個執行緒並發的錯誤了。 java中主要使用的就是ThreadLocal這個類別。

Join()方法

thread.Join把指定的執行緒加入到目前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。例如在執行緒B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。

t.join();      //使呼叫執行緒 t 在此之前執行完成。
t.join(1000);  //等待t 線程,等待時間是1000毫秒,超時就不等了

public class JoinTest implements Runnable{  

    public static int a = 0;  

    public void run() {  
        for (int k = 0; k < 5; k++) {  
            a = a + 1;  
        }  
    }  

    public static void main(String[] args) throws Exception {  
        Runnable r = new JoinTest();  
        Thread t = new Thread(r);  
        t.start();        
        t.join();//等待t线程完成后输出,可保证a=5;
        System.out.println(a);  
    }         
}

wait()

#Object的wait方法有三個重載方法,其中一個方法wait() 是無限期(一直)等待,直到其它執行緒呼叫notify或notifyAll方法喚醒目前的執行緒;另外兩個方法wait(long timeout) 和wait(long timeout, int nanos)允許傳入當前執行緒在被喚醒之前需要等待的時間,timeout為毫秒數,nanos為奈秒數。

notify()

notify方法只喚醒一個等待(物件的)執行緒並使該執行緒開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於作業系統對多線程管理的實作。

notifyAll()

notifyAll 會喚醒所有等待(物件的)線程,儘管哪一個執行緒將會第一個處理取決於作業系統的實作。
這些方法可以使用於「生產者-消費者」問題,消費者是在隊列中等待物件的線程,生產者是在隊列中釋放物件並通知其他線程的線程。

多執行緒的實作方式

● 繼承Thread類別建立執行緒類,重寫run方法,run方法就是代表執行緒需要完成的任務,呼叫執行緒物件的start()來啟動該線程,線程類別已經繼承了Thread類,所以不能再繼承其他父類。

class ThreadTest extends Thread {  

    Thread thread;  

    public ThreadTest(Thread thread) {  
      this.thread = thread;  
  }  

   @Override  
   public void run() {  
      synchronized (thread) {  
          System.out.println("getObjectLock");  
         try {  
             Thread.sleep(9000);  
       } catch (InterruptedException ex) {  
          ex.printStackTrace();  
         }  
           System.out.println("ReleaseObjectLock");  
    }  
   }  
 }

●  實作Runnable介面建立執行緒類,定義Runnable實作類,重寫run方法

  class RunnableImpl implements Runnable {  
    
      public void run() {  
          try {  
              System.out.println("Begin sleep");  
              Thread.sleep(2000);  
              System.out.println("End sleep");  
          } catch (InterruptedException e) {  
              e.printStackTrace();  
           }  
       }  
   }

● 實作Callable接口,重寫call()方法,call()作為執行緒的執行體,具有返回值

● 線程池,使用線程池產生線程物件java.util.concurrent.ExecutorService、java.util.concurrent.Executors;

#Java如何實現線程安全

● 互斥同步:推薦使用synchronized 關鍵字進行同步, 在concurrent包中有ReentrantLock類, 實現效果差不多. 還是推薦原生態的synchronized.
● 非阻塞同步:需要硬體指令完成.常用的指令有: Test-and-Set Fetch-and-Increment Swap Compare-and-Swap (CAS) Load-Linked/Store-Conditional (LL/SC) 典型的應用在AtomicInteger 中 
 ● 無同步方案:將變數保存在本地執行緒中,就不會出現多個執行緒並發的錯誤了。 java中主要使用的就是ThreadLocal這個類別。

Join()方法

thread.Join把指定的執行緒加入到目前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。例如在執行緒B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。

t.join();      //使呼叫執行緒 t 在此之前執行完成。
t.join(1000);  //等待t 線程,等待時間是1000毫秒,超時就不等了

public class JoinTest implements Runnable{  

    public static int a = 0;  

    public void run() {  
        for (int k = 0; k < 5; k++) {  
            a = a + 1;  
        }  
    }  

    public static void main(String[] args) throws Exception {  
        Runnable r = new JoinTest();  
        Thread t = new Thread(r);  
        t.start();        
        t.join();//等待t线程完成后输出,可保证a=5;
        System.out.println(a);  
    }         
}

wait()

#Object的wait方法有三個重載方法,其中一個方法wait() 是無限期(一直)等待,直到其它執行緒呼叫notify或notifyAll方法喚醒目前的執行緒;另外兩個方法wait(long timeout) 和wait(long timeout, int nanos)允許傳入當前執行緒在被喚醒之前需要等待的時間,timeout為毫秒數,nanos為奈秒數。

notify()

notify方法只喚醒一個等待(物件的)執行緒並使該執行緒開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於作業系統對多線程管理的實作。

notifyAll()

notifyAll 會喚醒所有等待(物件的)線程,儘管哪一個執行緒將會第一個處理取決於作業系統的實作。
這些方法可以使用於「生產者-消費者」問題,消費者是在隊列中等待物件的線程,生產者是在隊列中釋放物件並通知其他線程的線程。

以上是Java開發之多執行緒實作與執行緒安全的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn