Java 關於線程同步的問題

      Java 線程同步問題也不是什麼新鮮問題了,這裏做一個總結吧。

 

 

      線程同步時,調用一個 synchronized 的方法,所有的 synchronized 的方法都被鎖定,其他的方法不受影響。

 

看一個例子:

 

package com.ldq;

public class Test06 {

	private static Obj o1;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		o1 = new Obj();

		new Thread() {
			public void run() {
				o1.method01();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method02();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method03();
			}
		}.start();

	}
}

class Obj {

	synchronized void method01() {
		while (true) {
			System.out.println("method01");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	void method02() {
		while (true) {
			System.out.println("method02");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	synchronized void method03() {
		while (true) {
			System.out.println("method03");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

 

 

以上代碼輸出結果爲:

method01
method02
method02
method02
method02
method02
method01
method02
method02
method02

 

      分析:首先生成一個對象 o1 ,它有 3 個方法,其中 method01 和 method03 有關鍵字 synchronized 修飾,說明這兩個方法要做線程同步,而 method02 沒有關鍵字 synchronized 修飾,說明不用做同步。可見,對象加鎖操作是針對有 synchronized 關鍵字而言的。調用 synchronized 的方法,整個對象的所有 synchronized 的方法都被加鎖,但是其他的方法不受影響。

 

 

      sleep() 和 wait() 的區別

 

      sleep() 是 Thread 類的方法,wait() 是 Object 類的方法,由於所有類都是 Object 的子類,因此所有類都有 wait() 方法,從源代碼看 public final native void wait() ,wait() 方法是 final ,不允許重載或是覆蓋的,並且是 native ,是由本機接口實現的,與 JVM 的相關。

 

      sleep() 就是讓線程空轉,但是仍然佔用資源。wait() 用在 synchronized 修飾的方法裏,讓線程暫停,並釋放資源,直到有別的線程調用 notify() 或者 notifyAll() 方法喚醒。

 

      對某一個對象,wait() 讓線程進入等待池,notify() 喚醒一個線程,notifyAll() 喚醒所有的線程。

 

看代碼吧:

 

 

package com.ldq;

public class Test07 {

	private static MyObj o1;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		o1 = new MyObj();

		new Thread() {
			public void run() {
				o1.method01();
			}
		}.start();

		new Thread() {
			public void run() {
				o1.method02();
			}
		}.start();

	}
}

class MyObj {

	synchronized void method01() {
		while (true) {

			System.out.println("method01");

			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			notify();

			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	synchronized void method02() {
		while (true) {

			System.out.println("method02");

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			notify();

			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

 

 

 

輸出爲:

method01
method02
method01
method02
method01
method02

...

 

 

      分析:匿名線程1執行完method01後,notify() 等待的線程,wait() 釋放鎖,匿名線程2獲得鎖後輸出,notify() 等待的匿名線程1,自己 wait() 釋放鎖,此時,匿名線程1就可以繼續執行,如此循環 ...

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章