线程:sleep()、wait()、yield()和join()方法
2015-11-02 19:42
447 查看
欢迎大家访问我的博客[b]http://blog.csdn.net/mikejaps,专注于android
ios app 开发[/b]
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的锁.
* */
}
2. yield()
让当前运行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()的线程执行完毕后才能执行其它线程,在一定意义上,它可以实现同步的功能
* */
}
ios app 开发[/b]
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的锁.
* */
}
2. yield()
让当前运行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()的线程执行完毕后才能执行其它线程,在一定意义上,它可以实现同步的功能
* */
}
相关文章推荐
- poj 1363Rails
- hdu1789 Doing Homework again (贪心+优先队列)
- AIDL进阶
- adb server is out of date. killing... ADB server didn't ACK * failed to star
- AI 行为树框架
- 关于exchange使用foxmail下的pop3无法发送邮件exchange模式正常
- LightOJ 1021 - Painful Bases (状压dp)
- Quartz 任务调度(二)
- ZOJ 2967-C - Colorful Rainbows
- copy,assign,strong,retain,weak,readonly,nonatomic的区别
- Quartz 任务调度(一)
- AIDL初探(本地、进程)
- codeforces 242A Heads or Tails
- [11]Container With Most Water
- Kafka设计解析:Kafka High Availability (下)
- Codeforces Round #272 (Div. 2)A. Dreamoon and Stairs 水题
- WinAPI:PageSetupDlg、PagePaintHook
- 解决Visual Studio 2010新建工程时出现『1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt』错误
- This bundle is invalid. The bundle identifier contains disallowed characters.
- 几种常见的RAID工作模式讨论