线程常用方法辨析(1)
概述
1.sleep()方法
2.wait()方法
3.notify()/notifyAll()
4.总结
第1节 sleep()方法
1. sleep()方法的作用是让当前线程暂停指定的时间(毫秒)
2. sleep()方法只是暂时让出CPU的执行权,并不释放锁
3. 由于对象锁没有被释放,其他线程仍然无法访问这个对象
4. sleep()方法不需要在同步的代码块中执行,wait()方法必须要在同步的代码块中执行
5. sleep()可以通过interrupt()方法打断线程的暂停状态
6. sleep()只是线程的操作,用于短时间暂停线程,不涉及线程间通信
7. sleep()是Thread类的方法
代码语言:javascript复制public class SleepTest {
/**
* sleep()方法不会释放锁,因此线程是按照先后顺序执行的
*/
public synchronized void sleepMethod(){
System.out.println("Sleep start : "
Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Sleep end : "
Thread.currentThread().getName());
}
/**
* wait()方法会释放锁,因此一旦调用wait()方法就会造成其他线程运行
*/
public synchronized void waitMethod(){
System.out.println("Wait start : "
Thread.currentThread().getName());
synchronized (this){
try {
wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Wait end :"
Thread.currentThread().getName());
}
public static void main(String[] args) {
final SleepTest test1 = new SleepTest();
for(int i = 0; i < 5; i ){
new Thread(() -> test1.sleepMethod()).start();
}
try {
//暂停十秒,等上面程序执行完成
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----分割线-----");
final SleepTest test2 = new SleepTest();
for(int i = 0; i < 5; i ){
new Thread(() -> test2.waitMethod()).start();
}
}
}
执行结果如下:
代码语言:javascript复制Sleep start : Thread-0
Sleep end : Thread-0
Sleep start : Thread-4
Sleep end : Thread-4
Sleep start : Thread-3
Sleep end : Thread-3
Sleep start : Thread-2
Sleep end : Thread-2
Sleep start : Thread-1
Sleep end : Thread-1
-----分割线-----
Wait start : Thread-5
Wait start : Thread-6
Wait start : Thread-8
Wait start : Thread-7
Wait start : Thread-9
Wait end :Thread-6
Wait end :Thread-8
Wait end :Thread-9
Wait end :Thread-7
Wait end :Thread-5
第2节 wait()方法
1. wait()/notify()方法通常成对出现
2. wait()/notify()方法需要获取对象锁方可调用
3. wait()/notify()方法要写在同步代码块或者同步方法内
4. 一旦调用wait()方法,其他线程将可以访问这个对象
5. 当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,
同时失去了对象的锁,可以允许其它的线程执行一些同步操作。
6. wait()可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出中断异常
7. 重获对象锁:
a)设置wait()方法的参数,如wait(1000)表明借出去1秒钟之后,自动收回锁
b)让借锁的线程通知(notify)当前线程,借锁线程用完了当前线程马上就收回来
8. wait()/notify()是Object类的方法
第3节 notify()/notifyAll()
1. notify()唤醒在此对象监视器(对象锁)上等待的单个线程
2. 当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中
(synchronized部分会详细讲解等待池和锁池,此处简单理解即可)
3. 该线程将等待从锁池中获得锁,然后回到wait()前的现场
4. notifyAll()唤醒在此对象监视器(对象锁)上等待的所有线程
5. 唤醒的线程的顺序——LIFO(Last In First Out,后进先出)
6. wait()/notify()/notifyAll()涉及线程间的通信
代码语言:javascript复制public class WaitClassDemo {
private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
public static void main(String[] args) {
Object obj = new Object();
for (int i = 0; i < 5; i ) {
new WaitThread(i "", obj).start();
}
new NotifyThread(obj).start();
}
/**
* 调用wait()方法的线程
*/
static class WaitThread extends Thread {
Object obj;
public WaitThread(String name, Object obj) {
setName("WaitThread" name);
this.obj = obj;
}
@Override
public void run() {
synchronized (obj) {
System.out.println(sdf.format(new Date()) " " getName() " before wait()");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(sdf.format(new Date()) " " getName() " after wait()");
}
}
}
/**
* 调用notify()/notifyAll()
*/
static class NotifyThread extends Thread {
Object obj;
public NotifyThread(Object obj) {
setName("NotifyThread");
this.obj = obj;
}
@Override
public void run() {
synchronized (obj) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(sdf.format(new Date()) " NotifyThread before notify()");
// 唤醒所有线程 用notifyAll()会按照后进先出(LIFO)的原则恢复线程
obj.notifyAll();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(sdf.format(new Date()) " NotifyThread after notify()");
}
}
}
}
执行结果如下:
代码语言:javascript复制20:11:44 WaitThread0 before wait()
20:11:44 WaitThread4 before wait()
20:11:44 WaitThread3 before wait()
20:11:44 WaitThread2 before wait()
20:11:44 WaitThread1 before wait()
20:11:49 NotifyThread before notify()
20:11:54 NotifyThread after notify()
20:11:54 WaitThread1 after wait()
20:11:54 WaitThread2 after wait()
20:11:54 WaitThread3 after wait()
20:11:54 WaitThread4 after wait()
20:11:54 WaitThread0 after wait()
第4节 总结
1. wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态
2. 调用了wait()方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态
3. 对象调用了notify()方法就会通知某个正在等待这个对象的控制权的线程可以继续运行
4. 对象调用了notifyAll()方法就会通知所有等待这个对象控制权的线程继续运行
5. wait()方法有三个重载的方法wait()/wait(long)/wait(long,int)
6. sleep()方法的作用是让当前线程暂停指定的时间
7. sleep()方法只是暂时让出CPU的执行权,并不释放锁