1.
sleep-wait-yield区别
sleep是Thread类中的一个静态方法,其定义如下,
public static void sleep(long millis)throws InterruptedException
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响,如果指定睡眠的时间到达,则从阻塞状态转变成就绪状态,等待运行。
yield只是使当前线程重新回到可执行状态,让其它同一优先级的线程先运行,所以执行yield()的线程有可能进入到可执行状态后马上又被执行。
wait是Object类中定义的方法,与notify/notifyAll()在一起成对使用,提供线程间的等待-通知机制。
wait是Object类的方法,其定义如下,
public final void wait()throws InterruptedException//相当于wait(0)
public final void wait(long timeout)throws InterruptedException
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
调用wait()/notify()时,都必须首先获得相关的锁.而wait()被调用后,会释放之前进行同步块所获取到的锁。
synchronized(obj){
//wait(), notify(), notifyAll()
}
2.
wait-notify等待通知机制
wait/notify提供了一种通知机制,wait/notify关键字适用于一个线程通知另一个线程所需的条件状态已就绪,最常用于线程在循环中休眠直到获取特定条件的场景。
synchronized(lock){
//flag初始为false,是为了避免在执行wait()以前,notify()就已经执行了。
while(!flag){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//具体的业务逻辑在这里
obj.doSomething();
}
synchronized(lock){
flag = true;
lock.notify();
}
为什么要使用flag?
因为完全有可能notify()在wait()前被调用,这时wait()就会无限的等待下去,而没有任何通知。而加上flag,无论notify(),wait()谁先执行,都不会对最终结果造成任何的影响。假如,notify()先调用,那么wait所在的while-block将不会被执行,直接执行业务逻辑相关代码;如果wait()先执行,所在线程将阻塞,而此时notify()给出通知,wait()线程重新执行,并退出while-block,执行业务逻辑代码。
测试代码:
两个线程共享的locker和标识flag放在一个全局变量类中
class GlobalVar{
public final static Object locker = new Object();
public static boolean flag = false;
}
Waiter类
class Waiter extends Thread{
public void run(){
while(true){
synchronized(GlobalVar.locker){
while(!GlobalVar.flag){
try {
GlobalVar.locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
GlobalVar.flag = false;
}//synchronized end
//do something here
System.out.println("Waiter:完成一个新分配的任务");
}
}
}
Noticer类
class Noticer extends Thread{
public void run(){
synchronized(GlobalVar.locker){
GlobalVar.flag = true;
GlobalVar.locker.notify();
System.out.println("Noticer:分配一个新任务通知");
}
}
}
Main函数所在类
public class Test2 {
public static void main(String[] args) {
Noticer n = new Noticer();
Waiter w = new Waiter();
n.start();
w.start();
}
}
测试输出:
Noticer:分配一个新任务通知
Waiter:完成一个新分配的任务
使用wait-notify需要注意:
(1).调用
notify是随机的唤醒某一thread.而notifyAll则是唤醒所有等待的线程, 但只有一个线程可以在唤醒后lock object monitor,所以, notifyAll操作也是有利弊的.
(2).
wait、notify、notifyAll必须在synchronized修饰的代码块中执行,否则会在运行的时候抛出IllegalMonitorStateException异常
(3).在循环语句wait的时候一定要设定循环的条件--这样能够避免wait开始之前,线程所需的条件已经被其他线程提供了却依然开始此线程wait导致的时间消耗。同时,这种办法还能够保证你的代码不被虚假的信息唤醒。
(4).总是要保证在调用notify和notifyAll之前,能够提供符合线程退出等待的条件。否则会出现即使线程接收到通知信息,却不能退出循环等待的情况。
3.
join()方法
join方法是使当前线程阻塞,直到所引用的线程结束才激活.
public final void join()throws InterruptedException
4.
synchronized关键字
synchronized有四种使用方式:
synchronized method(){}
synchronized (obj)
static synchronized method(){}
synchronized(classname.class)
前面两个使用的锁是对象monitor,后面两者使用的是类monitor,都可以实现互斥访问。
一个对象只有一个对象monitor,一个类也只有一个类monitor。静态方法使用类monitor进行同步,而普通方法则使用对象monitor进行同步。
分享到:
相关推荐
2.3 线程本地存储(Java.lang.ThreadLocal) 15 2.4 线程阻塞 17 2.4.1 调用sleep(millisecond)使任务进入休眠状态 17 2.4.2 等待输出与输入 17 2.4.3 对象锁不可用 17 2.4.4 通过wait()使线程挂起。 17 2.5 线程...
60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable接口 用synchronized关键字修饰同步方法 反对使用...
分享的多线程技术不是告诉你什么是线程,线程的状态,而是我们在开发...1,wait notify 2,volatile 3,lock 4,join 5,并发工具 CountDownLatch 四: 项目中的应用 1,线程池技术 2,实际项目中的应用 3,获取返回值等
wait / sleep 并发 / 并行 Lock 使用Lock锁 可重入锁 公平锁 / 非公平锁 Synchronized / Lock 线程通讯 wait()、notify()和notifyAll() 虚假唤醒 Condition 定制化通信 多线程锁 并发下的集合类 List Set Map ...
描述一下Java线程的生命周期,线程状态; 线程之间的通信方式; 描述一下notify和notifyAll区别; synchronized关键字加在静态方法和实例方法的区别; 用锁的注意点; cas机制可能导致的问题ABA,什么是ABA; 程序开...
Thread.sleep//线程休眠 ((int)(Math.random() * 200));//以0~200ms的速度随机 } catch (InterruptedException e) //当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常 { e...
public synchronized void put(String name,String sex){ if (bFull){//可以取走数据 try{ wait(); //请等待,先不要写入数据,等待另一线程取走数据 }catch(Exception e){} }...
只有当别的线程在该对象上调用了 notify()或者notifyAll()方法,"Wait Set"队列中的线程才得到机会去竞争,但是只有一个线程获得对象的Monitor,恢复到运行态。"Wait Set"中的线程在Thread Dump中显示的状态为 in ...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、Overload...
41.sleep() 和 wait() 有什么区别? 42.notify()和 notifyAll()有什么区别? 43.线程的 run()和 start()有什么区别? 44.创建线程池有哪几种方式? 45.线程池都有哪些状态? 46.线程池中 submit()和 execute()方法有...
41. sleep() 和 wait() 有什么区别? 16 42. notify()和 notifyAll()有什么区别? 16 43. 线程的 run()和 start()有什么区别? 16 44. 创建线程池有哪几种方式? 17 45. 线程池都有哪些状态? 18 46. 线程池中 ...
│ 高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │ 高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │ 高并发编程第一阶段26...
│ 高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │ 高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │ 高并发编程第一阶段26...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 17、...
【多线程】简述synchronized 和java.util.concurrent.locks.Lock的异同? 90 【线程】ThreadLocal的作用 90 【Spring】什么是IOC和DI?DI是如何实现的 91 【Spring】spring中的IOC(控制反转)的原理 92 【Spring】...
DEF A notify() B wait() C notifyAll() D sleep() E.yield() F.synchronized(this) 7.构造BufferedInputStream的合适参数是哪个? AC A BufferedInputStream B BufferedOutputStream ...
wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。 同步和异步,在什么情况下分别使用? ...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
SimpleWebServer原型验证模块间通信同步模式下用synchronized同步块,Lock接口,Object自带的wait/yield/sleep/notify静态方法都是阻塞的,不太适用于短连接高并发的场景,尝试用非阻塞的方式更好的利用系统资源。...
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................