java wait() notify() notifyAll() synchronized关键字总结

java多线程并发执行的时候,如果需要多线程依次操作共享数据的时候,就需要对共享数据进行同步操作,就需要对同步代码块或者是同步方法就行加锁,具体就是将共享数据奖赏synchronized关键字,这样一次只能有一个线程能够访问同步块中的数据,只有当该线程释放锁之后,别的对象获得了锁之后,才能 访问同步代码块或者是方法。

wait()
使用方法    锁(即对象).wait()  
作用: 方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。条件:在调用wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。进入wait()方法后,当前线程释放锁。在从wait()返回前,线程与其他线程竞争重新获得锁。如果调用wait()时,没有持有适当的锁,则抛出IllegalMonitorStateException,它是RuntimeException的一个子类,因此,不需要try-catch结构。

notify()
使用方法 锁(对象).notify()
作用:唤醒其他休眠的线程中的一个,这个线程由系统确定该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用notify()时没有持有适当的锁,也会抛出IllegalMonitorStateException  一般情况下和wait()方法一起使用.

该方法用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知,并使它等待获取该对象的对象锁(notify后,当前线程不会马上释放该对象锁,wait所在的线程并不能马上获取该对象锁,要等到程序退出synchronized代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁),但不惊动其他同样在等待被该对象notify的线程们。当第一个获得了该对象锁的wait线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,会继续阻塞在wait状态,直到这个对象发出一个notify或notifyAll。这里需要注意:它们等待的是被notify或notifyAll,而不是锁。这与下面的notifyAll()方法执行后的情况不同。 

notifyAll()
 该方法与notify()方法的工作方式相同,重要的一点差异是:    
 notifyAll使所有原来在该对象上wait的线程统统退出wait的状态(即全部被唤醒,不再等待notify或notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll线程退出调用了notifyAll的synchronized代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出synchronized代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

下面举一个例子
两个线程一次打印出AB两个字母  总共打印十次
class  MultiThread
{
	public static void main (String[] args) throws Exception
	{
		Object self=new Object();
		Thread t1=new ThreadTest("a",self);
		Thread t2=new ThreadTest("b",self);
		t1.start();
		t2.start();

	}
}

class ThreadTest extends Thread
{
	
	private Object self;
	private String name;
	private int count=0;
	public ThreadTest(String name,Object self){
		
		this.self=self;
		this.name=name;
	}
	public void run()  {
		while(true){
			synchronized(self){
				System.out.println(name);

				count++;
				self.notify();
				//self.notifyAll();//效果相同
				if(count>=10){
					break;
				}
				try {
						self.wait();
						
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
			}
			//System.out.println("释放锁");
		}
	
	}
}

网上看到循环打印abc的一个例子 一并附上
import java.util.concurrent.atomic.AtomicInteger;

public class TestAsynTreadXunlei {
	public static void main(String argv[]) {
		
		AtomicInteger synObj = new AtomicInteger(0);
		
		TestPrint a = new TestPrint(synObj, "A", 0);
		TestPrint b = new TestPrint(synObj, "B", 1);
		TestPrint c = new TestPrint(synObj, "C", 2);
		
		a.start();
		
		b.start();
		c.start();
	}
}

class TestPrint extends Thread {
	
	private AtomicInteger synObj;
	private String name;
	private int flag;
	
	private int count = 0;
	
	public TestPrint(AtomicInteger synObj, String name, int flag) {
		this.synObj = synObj;
		this.name = name;
		this.flag = flag;
	}
	
	@Override
	public void run() {
		while (true) {
			synchronized (synObj) {
				if (synObj.get() % 3 == flag) {
					synObj.set(synObj.get() + 1);
					System.out.println(name);
					count++;
					synObj.notifyAll();
					if (count == 10) {
						break;
					}
				} else {
					try {
						synObj.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值