close

本來是想看Lock運作,但這跟資料存取有關,因此結果圖看起來沒問題。<<想看到錯誤的怪人

以下Oracle Lock說明,個人引用第一句......

Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. 

Lock介面提供更廣泛實作,能使用synchronized使synchronized更彈性。<<Lock是Interface不是Class

 

synchronized是為了防止在多執行緒下呼叫同Class造成存取上錯誤,而Lock是增加一層保險。((遭毆

因此個人改做成"逼多執行緒乖乖聽我的話",以下用Thread的join()和Interface ExecutorService這兩種方法解決。

 

程式參考資料:

Oracle Lock

Oracle ExecutorService

Oracle Executors

Java Artisan-join()

Difference between a Thread and an Executor in Java


結果圖:

lockExaple01.jpg

lockExaple02.jpg

lockExaple03.jpg

 

程式碼:

import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.locks.*;
import java.util.concurrent.*;

class Task implements Runnable
{
   private long tTimeS,tTimeE;
   private Lock lock;
   private int tNo,point;
   
   Task(int tNo)
   {setTask(new ReentrantLock(),tNo);}
 
   private synchronized void setTask(Lock lock,int tNo)
   {
     this.lock = lock;
     this.tNo = tNo;
   }
   private synchronized void setTransation(int point)
   {this.point = point;}
   private int getTransation(){return point;}
   //Thread run() Override
   public void run()
   {          
     if(lock.tryLock()){
       try{
           tTimeS = System.currentTimeMillis();
           lock.lock();
           System.out.println("Name:"+Thread.currentThread().getName()+" F"+tNo+"鎖定了... STime:"+tTimeS/1000.000);
           setTransation(tNo*100);                   
       }finally{
           System.out.println("F"+tNo+"設定值:"+getTransation());
           lock.unlock();
           tTimeE = System.currentTimeMillis();
           System.out.println("Name:"+Thread.currentThread().getName()+" F"+tNo+"解鎖了... Time:"+(tTimeE-tTimeS)/1000.000+"秒");
       }
     }             
   }
}

public class lockExample
{
   public static void main(String args[])
   {                                
      int threadNum = 10;
      long tTimeS,tTimeE,eTimeS,eTimeE;
      ExecutorService ex;
      
      //第一種方法:利用Thread.join()
      tTimeS = System.currentTimeMillis();     
      for(int x=0;x<threadNum;x++)
      {         
         Task ta = new Task(x);                      
         Thread taT = new Thread(ta);   
         taT.start();
         try{
             taT.join();//等待 x Thread結束才會繼續執行Main Thread
         }catch(InterruptedException ie)
         {System.out.println("InterruptedException");}        
      }
      tTimeE = System.currentTimeMillis();
      System.out.println("Threads have terminated... Time:"+(tTimeE-tTimeS)/1000.000+"秒");
      
      //第二種方法:利用newFixedThreadPool()限制執行Thread數量
      eTimeS = System.currentTimeMillis();
      ex = Executors.newFixedThreadPool(1);      
      for(int y=0;y<threadNum;y++)
      {
         Task ta = new Task(y);                      
         ex.execute(ta);
      }   
      ex.shutdown();
      try{
         if(ex.awaitTermination(1,TimeUnit.SECONDS))
         {
              eTimeE = System.currentTimeMillis();
              System.out.println("ExecutorService have terminated... Time:"+(eTimeE-eTimeS)/1000.000+"秒");              
         }         
         else System.out.println("ExecutorService is running");
      }catch(InterruptedException ie)
      {System.out.println("InterruptedException");}

      //為何顯示結果方法1會比方法2花時間呢?
      //其實這2個方法花費時間是一樣,用/*...*/註解掉其中1個方法就會發現了。
      //原因在先執行的程式碼(第一種方法)會有載入時間,當載入OK後續的程式碼(第二種方法)又再呼叫時就不用再載入。           
   }
}

 

第一種方法Thread-join()運作流程:

Main Thread >> 有join()要等待x=0 Thread結束 >> Main Thread >> 有join()要等待x=1 Thread結束......

第二種方法ExecutorService運作流程:

Main Thread >> newFixedThreadPool(1)代表能執行Thread只能一個 >> x=0 Thread丟入ThreadPool中 >>  x=1 Thread想丟入ThreadPool中,但需等x=0 Thread執行完畢......

 

Executors是Class,用newFixedThreadPool()控制Thread執行數量,把此環境設定存入ExecutorService。

ExecutorService是繼承Executor,而兩個都是Interface喔!

那有個問題,不能用Executor做嗎?

Executor只有execute()方法,所以ExecutorService就是Executor增強版,詳細請點上方程式參考資料。

Thread跟ExecutorService差別如下:

1.Thread是Class,ExecutorService是Interface。

2.ExecutorService能執行1個以上Interface Runnable,Thread只能執行1個Interface Runnable。

3.在ExecutorService下ThreadName是pool...,在Thread下ThreadName是Thread...。

4.想計算多執行緒時間,在Thread中沒join()那得到會是Main Thread執行完畢時間,但在ExecutorService中shutdown()和awaitTermination()能得到多執行緒執行完畢時間。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 o迷苓o 的頭像
    o迷苓o

    ~米漿牛奶~

    o迷苓o 發表在 痞客邦 留言(0) 人氣()