线程:sleep()、wait()、yield()和join()方法
来源:互联网 发布:网站数据库对接 编辑:程序博客网 时间:2024/04/28 15:00
欢迎大家访问我的博客http://blog.csdn.net/mikejaps,专注于android ios app 开发
1.sleep()和wait()
这两个方法都可以让调用它的线程沉睡(sleep)/停止运行(wait)指定的时间,到了这个时间,线程就会自动醒来,变为可运行状态(RUNNABLE)。public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException
public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException
Parameters:
millis - the length of time to sleep in milliseconds.毫秒数
nanos - 0-999999 additional nanoseconds to sleep.纳秒数
调用sleep()方法并不会让线程释放它所持有的同步锁;而且在这期间它也不会阻碍其它线程的运行。
当调用了某个对象的wait()方法时,当前运行的线程就会转入WAITING状态,等待别的线程再次调用这个对象的notify()或者notifyAll()方法唤醒它,或者到了指定的最大等待时间,线程自动醒来。如果线程调用了某个对象的wait()方法,这个线程就会释放这个对象所持有的同步资源(不会释放其他对象的同步锁)。
- package edu.hust.test;
- public class ThreadSleep implements Runnable {
- /*
- * 让线程睡眠的理由很多,比如(1)认为该线程运行得太快,需要减缓一下,以便和其他线程协调;(2)查询当时的股票价格,每睡5分钟查询一次,可以节省带宽,而且即时性要求也不那么高。
- * 注意:时间的精确性。线程醒来之后不会马上运行,而要等待cpu给其分配时间片。因此sleep()中指定的时间并不是线程不运行的精确时间!所以不能依赖sleep()方法提供十分精确的定时。
- * 我们可以看到很多应用程序用sleep()作为定时器,实际是不精确的。
- *
- *
- * Thread.sleep(5 * 1000)和Thread.currentThread().sleep(5 * 1000)没区别:都表示让当前线程sleep 5秒.
- * 一个是通过类获取静态方法,一个是通过实例对象获得静态方法(sleep()为静态方法).
- *
- * 注意:sleep并不是Thread的一个STATE
- */
- public void execute() {
- synchronized(this) {
- try {
- System.out.println(Thread.currentThread().getName() + ", sleep()前");
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + ", sleep()后");
- } catch (InterruptedException e) {
- System.out.println(Thread.currentThread().getName() + ", 谁把我吵醒了.....");
- }
- //此处如果使用System.err, 会有很意外的结果。System.out和System.err的区别请见blog
- System.out.println(Thread.currentThread().getName() + ", run()结束..进入TERMINATED状态");
- }
- }
- public void run() {
- execute();
- }
- public static void main(String[] args) throws InterruptedException {
- ThreadSleep threadSleep = new ThreadSleep();
- Thread[] threads = new Thread[5];
- System.out.println(Thread.currentThread().getName() + "线程的状态为:" + Thread.currentThread().getState());
- for (Thread thread : threads) {
- thread = new Thread(threadSleep);
- thread.start();
- if ("Thread-1".equals(thread.getName()) || "Thread-3".equals(thread.getName()))
- thread.interrupt();
- }
- }
- /*
- * 某次运行结果:
- * main线程的状态为:RUNNABLE
- * Thread-1, sleep()前
- * Thread-1, 谁把我吵醒了.....
- * Thread-1, run()结束..进入TERMINATED状态
- *
- * Thread-3, sleep()前
- * Thread-3, 谁把我吵醒了.....
- * Thread-3, run()结束..进入TERMINATED状态
- *
- * Thread-0, sleep()前
- * Thread-0, sleep()后
- * Thread-0, run()结束..进入TERMINATED状态
- *
- * Thread-2, sleep()前
- * Thread-2, sleep()后
- * Thread-2, run()结束..进入TERMINATED状态
- *
- * Thread-4, sleep()前
- * Thread-4, sleep()后
- * Thread-4, run()结束..进入TERMINATED状态
- *
- * 从运行结果可以得出很多结论, 其中之一是:调用sleep()方法并不会让线程释放它所持有的同步锁;而且在这期间它也不会阻碍其它线程的运行。
- *
- * */
- }
- package edu.hust.test;
- class MyThread1 implements Runnable {
- private Object obj;
- public MyThread1(Object o) {
- obj = o;
- }
- public void run() {
- synchronized (obj) { //这里是给obj对象(也就是str="爱吃土豆")加锁, 如写成synchronized (this), 则表示是给myThread1加锁.
- try {
- System.out.println("MyThread1进入wait状态");
- obj.wait();
- System.out.println("MyThread1被notify");
- } catch (InterruptedException e) {
- System.err.println("谁把我吵醒了.....");
- }
- }
- }
- }
- class MyThread2 implements Runnable {
- private Object obj;
- public MyThread2(Object o) {
- obj = o;
- }
- public void run() {
- synchronized (obj) { //这里是给obj对象(也就是str="爱吃土豆")加锁, 如写成synchronized (this), 则表示是给myThread2加锁.
- System.out.println("MyThread2调用notify()方法");
- obj.notify();
- }
- }
- }
- public class ThreadWait {
- public static void main(String[] args) {
- //错误的写法, 这里myThread1和myThread2操作的是两个不同的对象.
- //Thread myThread1 = new Thread(new MyThread1(new String("爱吃土豆")));
- //Thread myThread2 = new Thread(new MyThread2(new String("爱吃土豆")));
- //正确的写法, 这里myThread1和myThread2操作的是同一个对象.
- String str = "爱吃土豆";
- Thread myThread1 = new Thread(new MyThread1(str));
- Thread myThread2 = new Thread(new MyThread2(str));
- myThread1.start();
- myThread2.start();
- }
- /*
- * 运行结果:
- * MyThread1进入wait状态
- * MyThread2调用notify()方法
- * MyThread1被notify
- *
- * 这里使用了synchronized块来包装某个实例对象(String str = "爱吃土豆")的wait()和notify()方法, 这是由于调用这两个方法的时候线程必须获得同步锁.
- * 如果synchronized包装的不是同一个实例对象的wait()和notify()方法, 则表示给wait()和notify()加的锁不是同一把锁,eg:将synchronized(lock)改为synchronized(this).
- * 将会抛出java.lang.IllegalMonitorStateException, 告诉你current thread not owner.
- *
- * */
- /*
- * 摘录:
- * 多线程常用的一些方法: wait(),wait(long),notify(),notifyAll()
- * wait() 是使持有对象锁的线程释放锁;
- * wait(long) 是使持有对象锁的线程释放锁时间为long(毫秒)后,再次获得锁,wait()和wait(0)等价;
- * notify() 是唤醒一个正在等待该对象锁的线程,如果等待的线程不止一个,那么被唤醒的线程由jvm确定;
- * notifyAll 是唤醒所有正在等待该对象锁的线程.
- *
- * 应该优先使用notifyAll()方法, 因为唤醒所有线程比唤醒一个线程更容易让jvm找到最适合被唤醒的线程.
- * 对于上述方法,只有在当前线程中才能使用,否则报运行时错误java.lang.IllegalMonitorStateException: current thread not owner.
- * 从实现角度来分析:
- * 在线程调用wait()方法时,需要把它放到一个同步段里,否则将会出现"java.lang.IllegalMonitorStateException: current thread not owner"的异常。
- *
- * */
- }
- package edu.hust.test;
- public class ThreadWait2 implements Runnable {
- private Object monitor1 = new Object();
- private Object monitor2 = new Object();
- public void run() {
- synchronized (monitor1) {
- System.out.println("monitor1被锁住了");
- synchronized (monitor2) {
- System.out.println("monitor2被锁住了");
- try {
- System.out.println("monitor2进入wait()状态");
- monitor2.wait();
- } catch (InterruptedException e) {
- System.out.println("谁把我吵醒了.....");
- }
- }
- }
- }
- public void getMonitor() throws InterruptedException {
- Thread.sleep(3 * 1000); //让main Thread延迟3秒执行, 使myThread获得足够时间进行线程初始化
- synchronized (monitor2) {
- System.out.println("我取得了monitor2");
- }
- synchronized (monitor1) {
- System.out.println("我取得了monitor1");
- }
- }
- public static void main(String[] args) {
- ThreadWait2 threadWait2 = new ThreadWait2();
- Thread myThread = new Thread(threadWait2);
- myThread.start();
- try {
- threadWait2.getMonitor();
- } catch (InterruptedException e) {
- System.out.println("谁把我吵醒了.....");
- }
- }
- /*
- * 因为wait()方法没有被notify(), 所以程序不会自动结束. 但运行结果不会改变了:
- * monitor1被锁住了
- * monitor2被锁住了
- * monitor2进入wait()状态
- * 我取得了monitor2
- *
- * 分析:System.out.println("我取得了monitor1")这句话永远不会得到执行, 因为wait()被调用时只释放了monitor2的锁, 并没有释放monitor1的锁.
- * */
- }
让当前运行Thread放弃其所占用的cpu时间片,以便让其他Thread运行。用yield()方法的目的是让Thread能适当地轮转。但是,并不能保证达到此效果!因为,即使当前Thread放弃时间片,可是还有可能再次被JVM选中!也就是连任。
3. join()
- package edu.hust.test;
- public class ThreadJoin {
- public void run() {
- System.out.println("普通打印语句1");
- System.out.println("普通打印语句2");
- }
- public static void main(String[] args) throws InterruptedException {
- Thread myThread = new Thread() {
- public void run() {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- System.err.println("谁把我吵醒了.....");
- }
- System.out.println("线程:" + Thread.currentThread().getName() + " 启动了");
- }
- };
- myThread.start();
- myThread.join();
- new ThreadSeq().run();
- }
- /*
- * 没有t.join(), 运行结果为:
- * 普通打印语句1
- * 普通打印语句2
- * 线程:Thread-0 启动了
- *
- * 加入t.join(), 运行结果为:
- * 线程:Thread-0 启动了
- * 普通打印语句1
- * 普通打印语句2
- *
- * join():让当前Thread加入到myThread线程的尾部,意味着myThread线程运行结束之前,当前Thread不会运行。使调用join()的线程执行完毕后才能执行其它线程,在一定意义上,它可以实现同步的功能
- * */
- }
0 0
- 线程:sleep()、wait()、yield()和join()方法
- 线程:sleep()、wait()、yield()和join()方法
- 线程sleep()、wait()、yield()、join()方法 解析
- 线程常用方法-sleep(),join(),yield(),wait(),notify()...
- 线程sleep,wait,join,yield方法的区别
- java线程的sleep、yield、wait、join方法
- Java线程sleep,yield,join,wait方法详解
- 线程同步 synchronized sleep() wait() yield() join()(
- 线程同步 synchronized sleep() wait() yield() join()
- 线程的wait、sleep、join、yield详解
- sleep(),wait(),yield()和join()方法的区别
- sleep(),wait(),yield()和join()方法的区别
- sleep()、wait()、yield()和join()方法特点及区别
- sleep join yield wait
- sleep() wait() yield() join()
- sleep()、wait()、yield()、join()方法 解析
- sleep()、wait()、yield()、join()方法 解析
- JAVA中sleep()、wait()、yield()、join()方法
- 布局的重复使用
- bzoj1618【Usaco2008 Nov】Buying Hay 购买干草
- svn 命令行下常用的几个命令
- 黑马程序员——OC类的初始化与点语法
- Android依赖注入类库 Butter Knife的使用
- 线程:sleep()、wait()、yield()和join()方法
- 【设计模式】——原型模式VS模板方法模式
- iOS 多线程
- hdu 1200 To and Fro
- html和css结合的方式
- sun.misc.BASE64Encoder找不到jar包的解决方法
- oracle学习笔记--SQLPlus命令
- 椭圆函数与模函数(2012.10出版)(2013-01-16 09:34:57)
- Lake Counting 算法 第四集