java中wait()、this.wait()、super.wait()、object.wait()的使用区别

wait、notify和notifyAll方法是Object类的final native方法。所以这些方法不能被子类重写,Object类是所有类的超类,因此在程序中有以下三种形式调用wait等方法。

wait();//方式1:

this.wait();//方式2:

super.wait();//方式3

 

Object.wait()和Object.notify()和Object.notifyall()必须写在synchronized方法内部或者synchronized块内部,这是因为:这几个方法要求当前正在运行object.wait()方法的线程拥有object的对象锁。即使你确实知道当前上下文线程确实拥有了对象锁,也不能将object.wait()这样的语句写在当前上下文中.

(1) 线程持有当前对象的锁的结构

	public synchronized void waitAvailable() {
 
	}
	
	public void waitAvailable() {
		synchronized(this) {
			
		}
	}

我们知道wait()\notify()\notifyAll() 方法都是java.lang.Object类的 native方法,如果我们要在某个线程中的synchronized块中调用 wait()\notify()\notifyAll() 这几个方法,

有且只能调用线程所持有的那个锁的对象的wait()\notify()\notifyAll()方法。如果当前线程不是对象锁的持有者,则持有锁的方法就会抛出一个java.lang.IllegalMonitorStateException异常。

我们来看如下的代码实例:

public class Method {
	private int num = 10;
	
//	private Object lock = new Object();
	
	// 当前线程使用当前对象的锁
	public synchronized void method() {
	
		if (num > 8) {
			for (int i = 0; i<3 ;i++) {
				System.out.println(Thread.currentThread().getName() + " : " + num);
				num--;
			}
			try {
				System.out.println(Thread.currentThread().getName() + " wait begin ");
				//调用父类Object的native方法wait()
//				super.wait();
//			    this.wait();
     			wait();
				System.out.println(Thread.currentThread().getName() + " wait end ");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} 
		
		if (num <=7 && num > 1) {
			for (int i = 0; i<7 ;i++) {
				System.out.println(Thread.currentThread().getName() + " : " + num);
				num--;
			}
			//调用父类Object的native方法wait()
//			super.notify();
//			this.notify();		
			notify();
			System.out.println(Thread.currentThread().getName() + " notify ");
		}	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}

java 中任何类都是从java.lang.Object类的子类,那么任何类就继承了java.lang.Object类的公有的wait()\notify()\notifyAll() 这几个native方法。

若线程持有的是当前对象的锁 那么直接调用wait()、super.wait()、this.wait(),都是直接调用的当前对象的方法。所以在此处代码中调用wait()\notify()、super.wait()\super.notify、this.wait()\this.notify是一样的。

(2) 线程持有显示锁的结构

	private Object lock = new Object();
	
	public void method () {
		synchronized(lock) {
			
		}
	}
public class Method {
	private int num = 10;
	
	private Object lock = new Object();
	
 
	public synchronized void method() {
		// 当前线程持有对象lock的锁 那么下面应用条件对象时就必须调用锁的相应的方法
		synchronized(lock) {
			if (num > 8) {
				for (int i = 0; i<3 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				try {
					System.out.println(Thread.currentThread().getName() + " wait begin ");
					//调用父类Object的native方法wait()
//				super.wait();
//			    this.wait();
//     			wait();
					// 调用显示锁lock的wait()方法
					lock.wait();
					System.out.println(Thread.currentThread().getName() + " wait end ");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} 
			
			if (num <=7 && num > 1) {
				for (int i = 0; i<7 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				//调用父类Object的native方法wait()
//			super.notify();
//			this.notify();		
//			notify();
				// 调用显示锁lock的notify()方法
				lock.notify();
				System.out.println(Thread.currentThread().getName() + " notify ");
			}	
		}
	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}

上例中 我们让当前线程持有的是lock对象的锁,那么在使用条件对象时就必须调用当前锁lock对象的 wait()\notify()\notifyAll()方法。当然这些方法也是从java.lang.Object类继承而来。

如果当前线程持有的是对象A的锁,而使用条件对象时调用的是对象B的wait()\notify()方法组合,那么就会抛出一个java.lang.IllegalMonitorStateException异常

public class Method {
	private int num = 10;
	
	private Object lock = new Object();
	
 
	public synchronized void method() {
		// 当前线程持有当前对象this的锁
		synchronized(this) {
			if (num > 8) {
				for (int i = 0; i<3 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				try {
					System.out.println(Thread.currentThread().getName() + " wait begin ");
					//调用父类Object的native方法wait()
//				super.wait();
//			    this.wait();
//     			wait();
					// 使用条件对象时 调用显示锁lock的wait()方法  这样就会抛出异常
					lock.wait();
					System.out.println(Thread.currentThread().getName() + " wait end ");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} 
			
			if (num <=7 && num > 1) {
				for (int i = 0; i<7 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				//调用父类Object的native方法wait()
//			super.notify();
//			this.notify();		
//			notify();
				// 使用条件对象时 调用显示锁lock的notify()方法  这样就会抛出异常
				lock.notify();
				System.out.println(Thread.currentThread().getName() + " notify ");
			}	
		}
	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}
 
输出结果:
A : 10
A : 9
A : 8
A wait begin 
B : 7
B : 6
B : 5
B : 4
B : 3
B : 2
B : 1
Exception in thread "A" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:485)
	at com.renren.testwait.Method.method(Method.java:24)
	at com.renren.testwait.Method$1.run(Method.java:53)
	at java.lang.Thread.run(Thread.java:662)
Exception in thread "B" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at com.renren.testwait.Method.method(Method.java:42)
	at com.renren.testwait.Method$2.run(Method.java:59)
	at java.lang.Thread.run(Thread.java:662)

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java服务器端开发面试题 Java服务器端开发面试题篇1 Hashcode()和equals(), 明白背后的原理,包括hashcode()的用法,各自的区别,如何,何时覆盖,为何覆盖 区别new String()和 申明的字符串的区别,String不变量,堆上创建,何时栈上创建,传递变量时候的按值传 递 Comparable 接口,Comparator类,用来做比较,主要是用于集合,排序,插入等等 类初始化,变量初始化,静态变量,静态区,常量区等等 继承多态需要知道的有super, this, 相应的可能涉及到的设计模式 Java的内部类,有哪几种声明方式,有没有static的区别 集合,collection,array。 set, list, queue这些接口间的区别,set不可重复, arraylist的实现和linkedlist的实现区别,HashMap, HashTable。涉及到各种效率问题等,里面最好阅读一下源码 集合的遍历方法和使用iterator来遍历的区别,集合可否修改,能否删除其的一 个元素,然后size是否变化等等问题 JAVA垃圾回收,内存结构 异常的种类 Object类,哪些方法 文件读取, 字节流和字符流, 流的概念, reader, stream等; NIO(通道,缓冲区,选择器) Java服务器端开发面试题篇2 thread, start(), run() 多线程里面的关键字,wait, notfiy, 锁(synchronized), lock接口 线程状态,上下文切换,守护线程 消费者和生产者的几种实现方式,优缺点 进程间通信 同步容器类,并发容器类之间的区别 几个重要的数据结构,需要了解详细,最好能看过关键代码, copyOnWrite容器, ConcurrentHashMap 信号量, CountDownLatch, CyclicBarrier等类的使用 还有一些Future框架等等(这块我也知道的不多) Java服务器端开发面试题篇3 数据结构,线性列表,二叉树,完全二叉平衡树,B+树,图的表示。 树的先序,序,后序,层序遍历。能手写代码,递归和循环实现。 栈的使用 排序 常用的排序算法, 选择,冒泡,快排,堆排序,归并等。能手写代码,知道时间和空间复杂度,能做一些 代码上的改进。 动态规划和分治的区别,能根据题目想到这方面,简单的例子能写出来 图的算法 最好去leetcode上系统的刷一下题,不需要全部刷完,但是基本的类型都刷到,很 有帮助,代码能力也能提高 ----------------------- Java服务器端开发面试全文共2页,当前为第1页。 Java服务器端开发面试全文共2页,当前为第2页。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值