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就可以继续执行,如此循环 ...

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值