多线程之等待/通知机制(2)

1.方法wait()锁释放与notify()锁不释放

当方法wait()被执行后,锁被自动释放,但执行完notify()方法,锁却不自动释放。
示例代码如下:

package threadTest;

/**
 * @Author LiBinquan
 */
public class Service {
    public void testMethod(Object lock){
        try{
            synchronized (lock){
                System.out.println("begin wait()");
                lock.wait();
                System.out.println("end wait()");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

线程a:

package threadTest;

/**
 * @Author LiBinquan
 */
public class ThreadA extends Thread{
    private Object lock;
    public ThreadA(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        Service service = new Service();
        service.testMethod(lock);
    }
}

线程b:

package threadTest;

/**
 * @Author LiBinquan
 */
public class ThreadB extends Thread{
    private Object lock;
    public ThreadB(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        Service service = new Service();
        service.testMethod(lock);
    }
}

运行类:

package threadTest;

/**
 * @Author LiBinquan
 */
public class Run {
    public static void main(String[] args) {

            Object lock = new Object();
            ThreadA a = new ThreadA(lock);
            a.start();
            ThreadB b = new ThreadB(lock);
            b.start();
    }
}

输出:
在这里插入图片描述
如果将wait方法改成sleep方法,就成了同步效果,代码如下:

package threadTest;

/**
 * @Author LiBinquan
 */
public class Service {
    public void testMethod(Object lock){
        try{
            synchronized (lock){
                System.out.println("begin wait()");
                Thread.sleep(1000);
                System.out.println("end wait()");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

输出:
在这里插入图片描述
方法notify()被执行后,不释放锁。

package threadTest;

/**
 * @Author LiBinquan
 */
public class Service {
    public void testMethod(Object lock){
        try{
            synchronized (lock){
                System.out.println("begin wait() ThreadName = "+Thread.currentThread().getName());
                lock.wait();
                System.out.println("end wait() ThreadName = "+Thread.currentThread().getName());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public void synNotifyMethod(Object lock){
        try{
            synchronized (lock){
                System.out.println("begin notify() ThreadName = "+Thread.currentThread().getName()+" time = "+System.currentTimeMillis());
                lock.notify();
                Thread.sleep(5000);
                System.out.println("end notify() ThreadName = "+Thread.currentThread().getName()+" time = "+System.currentTimeMillis());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

线程a:

package threadTest;

/**
 * @Author LiBinquan
 */
public class ThreadA extends Thread{
    private Object lock;
    public ThreadA(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        Service service = new Service();
        service.testMethod(lock);
    }
}

线程NotifyThread

package threadTest;

/**
 * @Author LiBinquan
 */
public class NotifyThread extends Thread{
    private Object lock;
    public NotifyThread(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        Service service = new Service();
        service.synNotifyMethod(lock);
    }
}

线程SynNotifyMethodThread:

package threadTest;

/**
 * @Author LiBinquan
 */
public class SynNotifyMethodThread extends Thread{
    private Object lock;
    public SynNotifyMethodThread(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        Service service = new Service();
        service.synNotifyMethod(lock);
    }
}

运行类:

package threadTest;

/**
 * @Author LiBinquan
 */
public class Run {
    public static void main(String[] args) {

            Object lock = new Object();
            ThreadA a = new ThreadA(lock);
            a.start();
            NotifyThread b = new NotifyThread(lock);
            b.start();
            SynNotifyMethodThread c = new SynNotifyMethodThread(lock);
            c.start();
    }
}

输出:
在这里插入图片描述
由输出可得,必须执行完notify方法所在的同步synchronized代码后才释放锁。

2.当interrupt方法遇到wait方法

当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常。
测试代码如下:

package threadTest;

/**
 * @Author LiBinquan
 */
public class ServiceTwo {
    public void testMethod(Object lock){
        try{
            synchronized (lock){
                System.out.println("begin wait()");
                lock.wait();
                System.out.println("  end wait");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
            System.out.println("出现异常了,因为wait状态的线程被interrupt了!");
        }
    }
}

线程a:

package threadTest;

/**
 * @Author LiBinquan
 */
public class ThreadA extends Thread{
    private Object lock;
    public ThreadA(Object lock){
        super();
        this.lock = lock;
    }

    @Override
    public void run() {
        ServiceTwo service = new ServiceTwo();
        service.testMethod(lock);
    }
}

运行类:

package threadTest;

/**
 * @Author LiBinquan
 */
public class Run {
    public static void main(String[] args) {
        try{
            Object lock = new Object();
            ThreadA a = new ThreadA(lock);
            a.start();
            Thread.sleep(5000);
            a.interrupt();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

输出:
在这里插入图片描述
总结如下:
1.执行完同步代码块就会释放对象的锁。
2.在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。
3.在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放对象锁,而此线程对象会进入线程等待池中,等待被唤醒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值