Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

本文详细介绍了Java中用于线程控制的关键方法,包括sleep()、join()、yield()、wait()、notify()等,解释了它们的工作原理及应用场景,并对比了这些方法之间的差异。

内容转载自:http://dylanxu.iteye.com/blog/1322066

1、sleep()

使当前线程(即调用该方法的线程)暂停执行一段时间,进入阻塞状态,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。

例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。

总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。

sleep相对于yeild具有更好的系统可移植性与(CPU调度相关)。

2、join()

join()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。

 

3、yield()

该方法与sleep()类似,只是不能由用户指定暂停多长时间,进入就绪状态,并且yield()方法只能让同优先级或更高优先级的线程有执行的机会。

 

4、wait()和notify()、notifyAll()

 

这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用。synchronized关键字用于保护共享数据,阻止其他线程对共享数据的存取,但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。

wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。

notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

注意 这三个方法都是java.lang.Object的方法。



二、run和start()

把需要处理的代码放到run()方法中,start()方法启动线程将自动调用run()方法,这个由java的内存机制规定的。并且run()方法必需是public访问权限,返回值类型为void。


三、关键字synchronized

该关键字用于保护共享数据,当然前提条件是要分清哪些数据是共享数据。每个对象都有一个锁标志,当一个线程访问到该对象,被Synchronized修饰的数据将被"上锁",阻止其他线程访问。当前线程访问完这部分数据后释放锁标志,其他线程就可以访问了。



四、wait()和notify(),notifyAll()是Object类的方法,sleep()和yield()是Thread类的方法。

(1)、常用的wait方法有wait()和wait(long timeout);

void wait() 在其他线程调用此对象的 notify() 方法或者 notifyAll()方法前,导致当前线程等待。

void wait(long timeout)在其他线程调用此对象的notify() 方法 或者 notifyAll()方法,或者超过指定的时间量前,导致当前线程等待。

wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其他shnchronized数据可被别的线程使用。


wait()h和notify()因为会对对象的“锁标志”进行操作,所以他们必需在Synchronized函数或者 synchronized block 中进行调用。如果在non-synchronized 函数或 non-synchronized block 中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。。


(2)、Thread.sleep(long millis)必须带有一个时间参数。

sleep(long)使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;

sleep(long)可使优先级低的线程得到执行的机会,当然也可以让同优先级的线程有执行的机会;

sleep(long)是不会释放锁标志的。


(3)、yield()没有参数

sleep 方法使当前运行中的线程睡眠一段时间,进入不可以运行状态,这段时间的长短是由程序设定的,yield方法使当前线程让出CPU占有权,但让出的时间是不可设定的。

yield()也不会释放锁标志。

实际上,yield()方法对应了如下操作;先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把CPU的占有权交给次线程,否则继续运行原来的线程,所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。


sleep 方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,所以不可能让出较低优先级的线程此时获取CPU占有权。在一个运行系统中,如果较高优先级的线程没有调用sleep方法,也没有受到I/O阻塞,那么较低优先级线程只能等待所有较高优先级的线程运行结束,方可有机会运行。


yield()只是使当前线程重新回到可执行状态,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行,所以yield()方法只能使同优先级的线程有执行的机会。

### 一、Object 中包含哪些方法? `java.lang.Object` 是所有的根,它定义了以下公共(public)方法: | 方法名 | 描述 | |--------|------| | `public final Class<?> getClass()` | 返回对象的运行时信息 | | `public int hashCode()` | 返回对象的哈希码值 | | `public boolean equals(Object obj)` | 判断两个对象是否相等 | | `protected Object clone()` | 创建返回当前对象的一个副本(浅拷贝) | | `public String toString()` | 返回对象的字符串表示形式 | | `public final void notify()` | 唤醒一个等待在该对象上的线程 | | `public final void notifyAll()` | 唤醒所有等待在该对象上的线程 | | `public final void wait(long timeout)` | 让当前线程等待一段时间,直到被唤醒或超时 | | `public final void wait(long timeout, int nanos)` | 更精确的wait方法,参数包括毫秒纳秒 | | `public final void wait()` | 让当前线程无限期等待,直到被其他线程唤醒 | | `protected void finalize()` | 当垃圾回收器准备回收该对象调用(不推荐使用) | --- ### 二、`wait()` `sleep()` 的区别 | 对比点 | `wait()` | `sleep()` | |--------|----------|-----------| | **所属** | 属于 `Object` 方法 | 属于 `Thread` 的静态方法 | | **是否释放锁** | ✅ 会释放持有的对象锁 | ❌ 不会释放锁 | | **唤醒方式** | 需要配合 `notify()` / `notifyAll()` 使用 | 时间到自动恢复执行 | | **使用环境** | 必须在同步代码块或同步方法调用 | 可以在任意地方调用 | | **异常抛出** | 抛出 `InterruptedException` | 同样抛出 `InterruptedException` | | **作用对象** | 操作的是某个对象的锁机制 | 操作的是当前线程本身 | #### 示例对比: ```java // wait() 示例 synchronized (obj) { try { obj.wait(); // 线程进入等待释放obj的锁 } catch (InterruptedException e) { e.printStackTrace(); } } ``` ```java // sleep() 示例 try { Thread.sleep(1000); // 线程休眠1秒,不释放任何锁 } catch (InterruptedException e) { e.printStackTrace(); } ``` --- ### 总结 - `Object` 提供了 Java 中所有对象共有的基础行为; - `wait()` 与多线程协作有关,必须配合 `synchronized` 使用; - `sleep()` 是线程自身的休眠行为,不影响对象锁。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值