System.out.println(System.currentTimeMillis()+Thread.currentThread().getName()+" is Running");
}
//这个方法的关键字相当于给DeadLock对象上锁
synchronized public void getM(DeadLock dl){
dl.setM();
}
}
class T1 implements Runnable{
DeadLock m1 = null;
DeadLock m2 = null;
T1(DeadLock m1,DeadLock m2){
this.m1 = m1;
this.m2 = m2;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//执行m1的getM方法,将m1上锁了
m1.getM(m2);
}
}
}
class T2 implements Runnable{
DeadLock m1 = null;
DeadLock m2 = null;
T2(DeadLock m1,DeadLock m2){
this.m1 = m1;
this.m2 = m2;
}
@Override
public void run() {
while(true){
//执行m2的getM方法,将m2锁上了
m2.getM(m1);
}
}
}
执行这个程序一会儿,程序就会锁死。m1和m2同时被上锁。
内部线程通信 wait/notify 机制
通常应用于这么一种情况 线程A在修改某个变量的值,线程B需要线程A修改完成之后的变量的值,但是
线程B不知道线程A什么时候能够修改完成,所以线程B会不停的查探变量的值,但是这样做是比较耗费
系统资源的。所以我们就采用等待和通知机制来避免无限循环的使用。
一个最简单的wait/notify的例子
package cn.bj.brook.test;
public class MainRun {
int i = 0;
public void getM(){
//线程B到了这马上就被wait了,一直等到i大于10才能被通知
synchronized(this){
i=i+1;
System.out.println("In "+Thread.currentThread().getName()+" I is :"+i);
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void getB(){
//线程A到了判断i的条件,然后被通知
synchronized(this){
i=i+1;
System.out.println("In "+Thread.currentThread().getName()+" I is :"+i);
if(i>10){
this.notify();
}
}
}
public static void main(String[] args) {
MainRun mr = new MainRun();
T1 t1 = new T1(mr);
T2 t2 = new T2(mr);
Thread th1 = new Thread(t1,"ThreadA");
Thread th2 = new Thread(t2,"ThreadB");
th1.start();
th2.start();
}
}
class T1 implements Runnable{
MainRun mr = null;
T1(MainRun mr){
this.mr = mr;
}
@Override
public void run() {
while(true){
try {
System.out.println("In Thread T1 Running");
mr.getB();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class T2 implements Runnable{
MainRun mr = null;
T2(MainRun mr){
this.mr = mr;
}
@Override
public void run() {
while(true){
try {
System.out.println("In Thread T2 Running");
//线程B到了这马上就被wait了,一直等到i大于10才能被通知
mr.getM();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
记住一点wait()和notify()都是应用于提供锁的对象上的
上面的那个例子里,我们锁的都是MainRun的一个实例对象,让这个实例对象
去发出wait和notify的消息
线程2一进入MainRun的实例对象的getM方法就会被立刻锁上
唯有线程1进入MainRun的实例对象的getB方法,等i的值大于10的时候,才会发出
notify通知
notify通知,让所有在wait的线程都会立刻运行从而竞争对象锁,并不是所有的对象
都能拿到,只有一个线程对象能够拿到锁,从而执行。
wait方法刚好相反,wait方法使当前的调用线程进入深度睡眠,并且立刻放弃当前的对象锁。
上面的例子中,将synchronized关键字加在方法面前也是一样的。但是更多的推荐是
使用synchronized关键字来同步成员变量而非实例对象本身。
和sleep一样,处在wait中的线程是可以被interrupte的,被打断的线程会抛出一个
异常,通过对异常的捕