读实战java高并发程序设计笔记02--java并行程序进阶2

 下面我们来学习下Thread.sleep()函数,它的签名 如下

public static native void sleep (long mills) throws InterruptedException 

Thread.sleep()方法会让当前线程休眠若干时间,它会抛出一个interruptedException的异常,interruptedException不是运行时异常,也就是说程序必须捕获并且处理它,当线程在sleep()休眠的时候,如果被中断了,这个异常就会产生。


public static void main(String[] args) throws InterruptedException {
		
		Thread t1 = new Thread() {
			@Override
			public void run() {
				while (true) {
					if (Thread.currentThread().isInterrupted()) { 	//	判断线程是否被中断
					System.out.println("霖霖提醒您,该线程已经被中断了");
					break;
				}
					try {
						Thread.sleep(2000); // 将线程休眠2秒,线程被中断,则程序会抛出异常,继续往下执行,在catch中捕获中断
					} catch (InterruptedException e) {
						System.out.println("霖霖提示,当线程休眠的时候被中断");// 但是我们没有立即退出异常,而是进行了后续的处理,置上中断标志
						// 我们在这里设置中断状态
						Thread.currentThread().interrupt();
					}
					Thread.yield();
				}
			}
		};
		t1.start();
		Thread.sleep(2000);
		t1.interrupt();
	}

运行结果如下:

Thread.sleep()方法由于中断而抛出异常,此时,它会清除中断标记,如果不加处理,那么在下一次循环开始时,就无法捕获这个中断,所以在异常处理中,再次设置中断标记。


2.2.4 等待(wait) 和通知(notify)

为了支持多线程之间的协作,JDK提供了两个重要的接口线程等待和通知,这两个方法不在Thread中,而是属于Object类,也就意味着任何一个对象都可以调用这两个方法。

方法签名介绍:

public final void wait () throwsInterruptException

public final native void notify ()

当一个对象调用了wait()方法,当前线程就会在这个对象上等待,就会停止执行,转为等待状态,那么等待到合适结束呢?

线程一直等待到其他线程调用了notify方法为止,这时该对象就成为多个线程之间的有效通信手段。如果一个线程调用了obj.wait(),那么它就会进入object对象的等待队列,在这个等待的队列中可能会有多个线程,因为系统运行多个线程同时等待某一个对象。当obj.notify()被调用时,他就会从这个 等待的队列中随机选择一个线程,将其唤醒,在这里的选择是不公平的,和先后顺序无关,是一个随机的选择

除了notify方法外,还有一个notifyAll()的方法,它和notify方法功能基本一致,不同的是该方法唤醒的是等待队列中的所有等级的线程,而不是随机选择一个。

这里强调一下,wait()方法不要随意调用,它必须包含在所以synchronized语句中,无论是wait()或者notify()都需要首先获得目标对象的监视器,如下所示:


                                t1  线程                                                                                                                 t2   线程               

取得监视器---->object.wait()----->释放object监视器              取得object监视器---->object.notify()--->释放object监视器

等待object监视器-->重获object监视器-->继续执行

package cn.xuetao.test;

public class Test0223 {

	final static Object object = new Object();
	public static class T1 extends Thread {
		@Override
		public void run() {
			synchronized (object) {
				System.out.println(System.currentTimeMillis()+"霖霖提醒您,T1 start");
				try {
					System.out.println(System.currentTimeMillis()+"霖霖提醒您 ,T1 wait for object");
					object.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(System.currentTimeMillis()+"霖霖提醒您,T1 end");
			}
		}
	}
	public static class T2 extends Thread {
		@Override
		public void run() {
			synchronized (object) {
				System.out.println(System.currentTimeMillis()+"霖霖提醒您,T2 start! notify one thread");
				object.notify();
				System.out.println(System.currentTimeMillis()+"霖霖提醒您,T2 end");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args) {
		Thread t1 = new T1();
		Thread t2 = new T2();
		t1.start();
		t2.start();
	}
}

运行结果:


注意这个时间戳信息,可以看到,在T2通知T1继续执行后,T1并不能立即继续执行,而是要等待T2释放object锁,并重新成功获得锁后,才能继续执行,因此这里间隔2秒(因为T2休眠了2秒)

注意:Object.wait()和 Thread.sleep()方法都可以让线程等待若干时间,除了wait()方法可以被唤醒之外,另一个主要的区别在于wait()方法会释放目标对象的锁,而Thread.sleep()方法不会释放任何资源。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值