多執行緒同步問題-練習題3-筆記整理
阿新 • • 發佈:2019-01-05
練習題3:
程式同時啟用了4個執行緒去呼叫TestDo.doSome()方法,由於TestDo.doSome方法內部的程式碼是先暫停1秒,
然後在輸出以秒為單位的當前時間值,所以,會打印出4個相同的時間值,如下所示:
4:4:1258199615
1:1:1258199615
3:3:1258199615
1:1:1258199615
修改程式碼,如果有幾個執行緒呼叫TestDo.doSome方法時,傳遞進去的key相等,則這幾個執行緒應互斥排隊輸出結果,
即當有有個執行緒的key都是“1”時,他們中的一個要比其他執行緒晚1秒輸出結果。
提示:對key相同的執行緒處理時,使用同一把鎖,阻塞
題目程式碼示例:
public class Test3 extends Thread{ private TestDo1 testDo; private String key; private String value; public Test3(String key1,String key2, String value) { this.testDo = TestDo1.getInstance(); this.key = key1+key2; this.value = value; } public static void main(String[] args) { Test3 a=new Test3("1","","1"); Test3 b=new Test3("2","","2"); Test3 c=new Test3("3","","3"); Test3 d=new Test3("4","","4"); System.out.println("begin:"+System.currentTimeMillis()/1000); a.start(); b.start(); c.start(); d.start(); } public void run(){ testDo.doSome(key, value); } } class TestDo1{ private TestDo1(){} private static TestDo1 _instance=null; public static TestDo1 getInstance(){ if(_instance==null){ synchronized (TestDo1.class) { if(_instance==null){ _instance=new TestDo1(); } } } return _instance; } public static void doSome(Object key,String value){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(key+":"+value+":"+System.currentTimeMillis()/1000); } }
修改後程式碼示例:
public class Test3_1 extends Thread{ private TestDo1 testDo; private String key; private String value; public Test3_1(String key1,String key2, String value) { this.testDo = TestDo1.getInstance(); this.key = key1+key2; this.value = value; } public static void main(String[] args) { Test3_1 a=new Test3_1("1","","1"); Test3_1 b=new Test3_1("2","","2"); Test3_1 c=new Test3_1("3","","3"); Test3_1 d=new Test3_1("1","","1"); System.out.println("begin:"+System.currentTimeMillis()/1000); a.start(); b.start(); c.start(); d.start(); } public void run(){ testDo.doSome(key, value); } } class TestDo1{ private TestDo1(){} private static TestDo1 _instance=null; public static TestDo1 getInstance(){ if(_instance==null){ synchronized (TestDo1.class) { if(_instance==null){ _instance=new TestDo1(); } } } return _instance; } ArrayList<String> list=new ArrayList<String>(); public void doSome(Object key,String value){ String str=(String)key; //關鍵點,維護key相同,使用相同的鎖阻塞 if(list.contains(key)){ Iterator iterator = list.iterator(); while(iterator.hasNext()){ String tmp = (String)iterator.next(); if(tmp.equals(key)){ str=tmp; } } }else{ list.add((String)key); } synchronized (str) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(key+":"+value+":"+System.currentTimeMillis()/1000); } } }