1. 程式人生 > >多執行緒同步問題-練習題3-筆記整理

多執行緒同步問題-練習題3-筆記整理

練習題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);
		}
	}
}