1. 程式人生 > >理解執行緒的join方法

理解執行緒的join方法

在多執行緒環境下很難保證結果的一致性,多執行緒帶來的好處就是並行處理提升效率,弊端就是出現了問題很難定位,可以看個例子就明白了,請將下面的程式碼拷到本地去執行,就會發現每次執行的結果不一樣。

     程式碼1

public class JoinDemo {
	public static void main(String[] args) {
		Thread thread1 = new Thread(()->{
			System.out.println("1");
		});
				
		Thread thread2 = new Thread(()->{
			System.out.println("2");
		});
				
		Thread thread3 = new Thread(()->{
			System.out.println("3");
		});
		
		thread1.start();
		thread2.start();
		thread3.start();
	}
}

怎麼樣才能每次結果都是123,那麼就需要使用join。看下面的程式碼

    程式碼2

public class JoinDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread thread1 = new Thread(()->{
			System.out.println("1");
		});
		
		
		Thread thread2 = new Thread(()->{
			System.out.println("2");
		});
		
		
		Thread thread3 = new Thread(()->{
			System.out.println("3");
		});
		
		thread1.start();
		thread1.join();
		thread2.start();
		thread2.join();
		thread3.start();
	}
}

為什麼現在無論程式執行多少次,結果都是123,那就需要去看看join的原始碼到底做了什麼如此神奇。

     程式碼3

public final synchronized void join(long millis)
		    throws InterruptedException {
		        long base = System.currentTimeMillis();
		        long now = 0;

		        if (millis < 0) {
		            throw new IllegalArgumentException("timeout value is negative");
		        }

		        // 傳入的就是0
		        if (millis == 0) {
		            while (isAlive()) {
		            	// 等待0秒,起到阻塞的作用
		                wait(0);
		            }
		        } else {
		            while (isAlive()) {
		                long delay = millis - now;
		                if (delay <= 0) {
		                    break;
		                }
		                wait(delay);
		                now = System.currentTimeMillis() - base;
		            }
		        }
		    }
}

好,那我們是否能自己寫程式碼實現join方法類似的功能呢?當然可以,對程式碼2進行稍微的修改就可以了。

thread1.start();
Thread.sleep(3);
thread2.start();
Thread.sleep(3);
thread3.start();
多執行緒還有很多技術能控制執行緒的執行和阻塞,通過阻塞實現一些意向不到的效果,後續再分享。