本來是想看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這兩種方法解決。
程式參考資料:
Difference between a Thread and an Executor in Java
結果圖:
程式碼:
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()能得到多執行緒執行完畢時間。