精华内容
下载资源
问答
  • obj.wait()/obj.wait(long timeout)是Object中的方法,当线程调用wait()方法,当前线程释放对象锁,进入等待队列。 obj.notify()/obj.nogifyAll()是Object中的方法,唤醒在此对象上wait()的单个或者所有线程。 测试...

    wait()、notify()、notifyAll()用法

    • obj.wait()/obj.wait(long timeout)是Object中的方法,当线程调用wait()方法,当前线程释放对象锁,进入等待队列。
    • obj.notify()/obj.nogifyAll()是Object中的方法,唤醒在此对象上wait()的单个或者所有线程。

    测试代码:

    public class ThreadWaitNotify {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    //创建一个线程池
    
    ExecutorService executorService = Executors.newCachedThreadPool();
    
    //创建DemoTest对象
    
    DemoTest demoTest = new DemoTest();
    
    //用线程池创建线程异步执行waitTest方法
    
    executorService.submit(() -> demoTest.waitTest());
    
    //用线程池创建线程异步执行notifyTest方法
    
    executorService.submit(() -> demoTest.notifyTest());
    
    }
    
    
    //测试wait和notify测试demo
    
    static class DemoTest {
    
    //唤醒线程
    
    public synchronized void notifyTest() {
    
    System.out.println("方法notifyTest开始执行了");
    
    notify();
    
    System.out.println("方法notifyTest执行结束了");
    
    }
    
    //执行wait操作将线程挂起,注意必须结合synchronized使用
    
    public synchronized void waitTest() {
    
    System.out.println("方法waitTest开始执行了");
    
    try {
    
    wait();
    
    } catch (InterruptedException e) {
    
    e.printStackTrace();
    
    }
    
    System.out.println("方法waitTest执行结束了");
    
    }
    
    }
    
    }

    打印日志:

     
    1. 方法waitTest开始执行了

    2. 方法notifyTest开始执行了

    3. 方法notifyTest执行结束了

    4. 方法waitTest执行结束了

    从日志中我们可以看出waitTest方法阻塞直到被notifyTest唤醒

    二、await()、signal()、signalAll()用法

    java.util.concurrent类库中提供的Condition类来实现线程之间的协调。

    • condition.await()/condition.await(long time, TimeUnit unit):通过condition调用,当前线程释放对象锁。
    • condition.signal()/condition.signalAll():通过signal或者signalAll方法唤醒await挂起的线程。

    测试代码:

     
    public class ThreadAwaitSignal {
    
    public static void main(String[] args) {
    
    //创建一个线程池
    
    ExecutorService executorService = Executors.newCachedThreadPool();
    
    //创建DemoTest对象
    
    DemoTest demoTest = new DemoTest();
    
    //用线程池创建线程异步执行awaitTest方法
    
    executorService.submit(() -> demoTest.awaitTest());
    
    //用线程池创建线程异步执行signalTest方法
    
    executorService.submit(() -> demoTest.signalTest());
    
    }
    
    
    /**
    
    * 使用java.util.conncurrent类中提供了Condition类来实现线程之间的协调
    
    * 可以在Condition上调用await()方法使线程挂起
    
    * 其他线程调用signal()或者signalAll()来唤醒线程
    
    */
    
    static class DemoTest {
    
    //定义一个Lock对象用来获取Condition对象
    
    private Lock lock = new ReentrantLock();
    
    private Condition condition = lock.newCondition();
    
    //唤醒线程
    
    public void signalTest() {
    
    lock.lock();
    
    try {
    
    System.out.println("方法signalTest开始执行了");
    
    condition.signalAll();
    
    System.out.println("方法signalTest执行结束了");
    
    } catch (Exception e) {
    
    e.printStackTrace();
    
    } finally {
    
    lock.unlock();
    
    }
    
    }
    
    
    //结合lock锁实现Condition的await
    
    public void awaitTest() {
    
    lock.lock();
    
    try {
    
    System.out.println("方法awaitTest开始执行了");
    
    condition.await();
    
    System.out.println("方法awaitTest执行结束了");
    
    } catch (InterruptedException e) {
    
    e.printStackTrace();
    
    } finally {
    
    lock.unlock();
    
    }
    
    }
    
    }
    
    }

    打印日志:

     
    1. 方法awaitTest开始执行了

    2. 方法signalTest开始执行了

    3. 方法signalTest执行结束了

    4. 方法awaitTest执行结束了

    从日志中国可以看出我们得到了和wait同样的效果。

    三 、yield()、join()用法

    • Thread.yield():一定是当前线程调用此方法,当前线程放弃获取CPU的时间片,由运行态转变为就绪态,让操作系统中再次选择线程执行。作用:让相同优先级的线程轮流执行,但并不能保证轮流执行,根据解释我们了解到,转成就绪态的的线程还有可能再次选中执行。Thread.yield()方法不会导致阻塞。
    • t.join()/t.join(long millis):当前线程调用t2.join()方法,当前线程阻塞但是不会释放对象锁,直到t2线程执行完毕或者millis时间到,则当前的线程恢复就绪状态。作用:让优先级比较高的线程优先执行。

    yield测试代码:

     
    //yield放弃CPU时间片
    
    public static void yieldTest(){
    
    //定义一个线程
    
    Thread thread = new Thread(() -> {
    
    System.out.println(Thread.currentThread().getName() + ": 测试线程开始执行。。。");
    
    try {
    
    Thread.sleep(5000);
    
    } catch (InterruptedException e) {
    
    e.printStackTrace();
    
    }
    
    System.out.println(Thread.currentThread().getName() + ": 测试线程执行结束了。");
    
    });
    
    thread.start();
    
    System.out.println(Thread.currentThread().getName() + ": 执行yield方法");
    
    Thread.yield();
    
    System.out.println(Thread.currentThread().getName() + ": 主线程开始执行");
    
    }

    打印结果:

     
    1. main: 执行yield方法

    2. main: 主线程开始执行

    3. Thread-0: 测试线程开始执行。。。

    4. Thread-0: 测试线程执行结束了。

    可以看出虽然主线程调用了yield,但是仍然又开始执行了,因此但并不能保证轮流执行。

    join测试代码:

     
    //join抢占CPU时间片
    
    public static void joinTest() throws InterruptedException {
    
    //定义一个线程
    
    Thread thread = new Thread(() -> {
    
    System.out.println(Thread.currentThread().getName() + ": 测试线程开始执行。。。");
    
    try {
    
    Thread.sleep(5000);
    
    } catch (InterruptedException e) {
    
    e.printStackTrace();
    
    }
    
    System.out.println(Thread.currentThread().getName() + ": 测试线程执行结束了。");
    
    });
    
    thread.start();
    
    System.out.println(thread.getName() + ": 执行join方法");
    
    thread.join();
    
    System.out.println(Thread.currentThread().getName() + ": 主线程开始执行");
    
    }

    打印日志:

     
    1. Thread-0: 执行join方法

    2. Thread-0: 测试线程开始执行。。。

    3. Thread-0: 测试线程执行结束了。

    4. main: 主线程开始执行

    从日志中我们可以看出主线程在线程执行完成后才开始执行。

    四、wait()、await()、sleep()、yield、join对比

    通过表格对比(join的情况下,t1指代当前线程,t2代表其他线程)

     

    aa69709410f0ad087e6d4937fac63b53.png

    展开全文
  • wait是指在一个已经进入了同步锁的线程内...但不是马上得到锁,因为锁还在别人手里,别人还没释放),调用wait方法的一个或多个线程就会解除wait状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运...

    wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放),调用wait方法的一个或多个线程就会解除wait状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运行。

    1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。

    2)当前线程必须拥有此对象的monitor(即锁),才能调用某个对象的wait()方法能让当前线程阻塞,

    (这种阻塞是通过提前释放synchronized锁,重新去请求锁导致的阻塞,这种请求必须有其他线程通过notify()或者notifyAll()唤醒重新竞争获得锁)

    3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;

    (notify()或者notifyAll()方法并不是真正释放锁,必须等到synchronized方法或者语法块执行完才真正释放锁)

    4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程,唤醒的线程获得锁的概率是随机的,取决于cpu调度

    例子1(错误使用导致线程阻塞):三个线程,线程3先拥有sum对象的锁,然后通过sum.notify()方法通知等待sum锁的线程去获得锁,但是这个时候线程1,2并没有处于wait()导致的阻塞状态,而是在synchronized方法块处阻塞了,所以,这次notify()根本没有通知到线程1,2。然后线程3正常结束,释放掉sum锁,这个时候,线程1就立刻获得了sum对象的锁(通过synchronized获得),然后调用sum.wait()方法释放掉sum的锁,线程2随后获得了sum对象的线程锁(通过synchronized获得),这个时候线程1,2都处于阻塞状态,但是悲催的是,这之后再也没有线程主动调用sum.notify()或者notifyAll()方法显示唤醒这两个线程,所以程序阻塞

    Java代码  

    public class CyclicBarrierTest {

    public static void main(String[] args) throws Exception {

    final Sum sum=new Sum();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread3 get lock");

    sum.sum();

    sum.notifyAll(); //此时唤醒没有作用,没有线程等待

    Thread.sleep(2000);

    System.out.println("thread3 really release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread1 get lock");

    sum.wait();//主动释放掉sum对象锁

    System.out.println(sum.total);

    System.out.println("thread1 release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread2 get lock");

    sum.wait();  //释放sum的对象锁,等待其他对象唤醒(其他对象释放sum锁)

    System.out.println(sum.total);

    System.out.println("thread2 release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    }

    }

    class Sum{

    public Integer total=0;

    public void  sum() throws Exception{

    total=100;

    Thread.sleep(5000);

    }

    }

    运行结果:

    Java代码  

    thread3 get lock

    thread3 really release lock

    thread2 get lock

    thread1 get lock

    //程序后面一直阻塞

    例子2:还是上面程序,顺序不同,把线程3放到最下面。最后线程1,2都因为没有再次获得线程导致线程阻塞

    运行过程:

    线程1先运行获得sum对象锁(通过synchronized),但是随后执行了sum.wait()方法,主动释放掉了sum对象锁,然后线程2获得了sum对象锁(通过synchronized),也通过sum.wait()失去sum的对象锁,最后线程3获得了sum对象锁(通过synchronized),主动通过sum.notify()通知了线程1或者2,假设是1,线程1重新通过notify()/notifyAll()的方式获得了锁,然后执行完毕,随后线程释放锁,然后这个时候线程2成功获得锁,执行完毕。

    Java代码  

    public class CyclicBarrierTest {

    public static void main(String[] args) throws Exception {

    final Sum sum=new Sum();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread1 get lock");

    sum.wait();//主动释放sum对象锁,等待唤醒

    System.out.println(sum.total);

    System.out.println("thread1 release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread2 get lock");

    sum.wait();  //主动释放sum对象锁,等待唤醒

    System.out.println(sum.total);

    System.out.println("thread2 release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    new Thread(new Runnable() {

    @Override

    public void  run() {

    try {

    synchronized (sum) {

    System.out.println("thread3 get lock");

    sum.sum();

    sum.notifyAll();//唤醒其他等待线程(线程1,2)

    Thread.sleep(2000);

    System.out.println("thread3 really release lock");

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    }

    }

    class Sum{

    public Integer total=0;

    public void  sum() throws Exception{

    total=100;

    Thread.sleep(5000);

    }

    }

    执行结果:

    Java代码  

    thread1 get lock

    thread2 get lock

    thread3 get lock

    thread3 really release lock

    100

    thread2 release lock

    100

    thread1 release lock

    转自 https://blog.csdn.net/azhegps/article/details/63031562

    展开全文
  • }当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁.之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:synchronized...

    synchronized(obj) {

    while(!condition) {

    obj.wait();

    }

    obj.doSomething();

    }

    当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁.

    之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:

    synchronized(obj) {

    condition = true;

    obj.notify();

    }

    需要注意的概念是:

    # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {…} 代码段内。

    # 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {…} 代码段内唤醒A。

    # 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。

    # 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。

    # obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。

    # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

    分享到:

    2009-08-19 23:20

    浏览 4825

    评论

    展开全文
  • sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停...wait()是Object类的方法,调用对象wait()方法导致当前线程放弃对象(线程暂停执行),进入对象的等待池(waitpool),只有调用对象的...

    sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程

    暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保

    持,因此休眠时间结束后会自动恢复(线程回到就绪状态,请参考第66题中的线

    程状态转换图)。wait()是Object类的方法,调用对象的wait()方法导致当前线

    程放弃对象的锁(线程暂停执行),进入对象的等待池(waitpool),只有调用

    对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池

    (lockpool),如果线程重新获得对象的锁就可以进入就绪状态。

    补充:可能不少人对什么是进程,什么是线程还比较模糊,对于为什么需要多线

    程编程也不是特别理解。简单的说:进程是具有一定独立功能的程序关于某个数

    据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独立单位;线

    程是进程的一个实体,是CPU调度和分派的基本单位,是比进程更小的能独立运

    行的基本单位。线程的划分尺度小于进程,这使得多线程程序的并发性高;进程

    在执行时通常拥有独立的内存单元,而线程之间可以共享内存。使用多线程的编

    程通常能够带来更好的性能和用户体验,但是多线程的程序对于其他程序是不友

    好的,因为它可能占用了更多的CPU资源。当然,也不是线程越多,程序的性能

    就越好,因为线程之间的调度和切换也会浪费CPU时间。时下很时髦的Node.js

    就采用了单线程异步I/O的工作模式。

    展开全文
  • Android中对象锁

    2021-06-09 01:21:10
    Android中对象锁wait()和notify()基本概念:对象锁synchronized(object){….}用法在以上的代码块中只能由一个线程执行!!!wait()、notify()是用在这个代码块当中的。wait()可以使当前线程A马上失去对象锁并且...
  • 在区别之前,我们首先先了解一下关于对象锁,类锁的相关概念(当时查阅的详细地址:http://www.importnew.com/20444.html,该作者对类锁和对象锁进行了详细的举例分析)对象锁,类锁在java虚拟机中,每个对象和类在...
  • Java多线程里面join方法会使被阻塞线程释放对象锁吗?问题描述如下:public class HelloJava {public static void main(String[] args) {Object oo = new Object();MyThread t1 = new MyThread("线程t1--", oo);...
  • 由于等待一个锁定线程只有在获得这把...3. 在执行同步代码块的过程中,执行了所属对象wait()方法,这个线程会释放,进行对象的等待池。除了以上情况外,只要持有的此案吃还没有执行完同步代码块,就不会释放...
  • Java_多线程_锁释放问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的。在以下情况...
  • 由于等待一个锁定线程只有在获得这把...3. 在执行同步代码块的过程中,执行了所属对象wait()方法,这个线程会释放,进行对象的等待池。除了以上情况外,只要持有的线程还没有执行完同步代码块,就不会释放...
  • 先来我们来看下相关定义:wait() :调用该方法的线程进入WATTING状态,只有等待另外线程的通知或中断才会返回,调用wait()方法后,会释放对象wait(long):超时等待最多long毫秒,如果没有通知就超时...
  • 一、对象头 在 JVM 中,对象在内存中分为三块区域: 对象头:标记字段和类型指针。一会介绍 实例数据:这部分主要是存放类的数据信息,父类的信息。 对齐填充:由于虚拟机要求对象起始地址必须是8字节的整数倍,...
  • wait()是 Object 类的方法,调用对象wait()方法导致当前线 程放弃对象(线程暂停执行),进入对象的等待池(wait pool),只有调用 对象的 notify()方法(或 notifyAll()方法)时才能唤醒等待池中的线程进入...
  • 内容导航线程同步Producer—ConsumerProducer类,主要定义生产者线程的run方法Consumer类,主要是定义run方法起始类,主要是创建一个队列,并用队列启动线程队列结点类队列类Queue使用synchronized上怎么解决死锁...
  • wait()方法是让当前线程等待的,即让线程释放了对共享对象,不再继续向下执行。 wait(long timeout)方法可以指定一个超时时间,过了这个时间如果没有被notify()唤醒,则函数还是会返回。如果传递一个负数time...
  • 条件变量, Waitgroup, Once, 临时对象池Pool和原子操作 一、互斥和读写 关于相信大家都很熟悉了,因此这里不再对锁进行过多的描述,只是简单的带过一下。如果读者们想了解互斥和读写的基本使用和例子,...
  • java synchronized wait

    2021-03-13 14:19:50
    在多个线程要互斥访问数据,但线程间需要同步时——例如任务分多个阶段,特定线程负责特定阶段的情况,经常合作使用synchronized 和 wait()/**** 计算输出其他线程计算的数据*@author**/public classMain {public ...
  • 1. wait方法 当条件不成熟时就等待 运行分为三步: 1.释放 2.等到通知 3.收到通知后尝试重新获取继续往下执行 wait方法必须在synchronized代码内部使用 2. notify方法 当条件成熟时,通知指定线程来工作 notify...
  • JAVA sleep() & wait()

    2021-02-28 10:52:18
    对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。...而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象...
  • Java多线程 wait notify

    2021-03-10 09:51:32
    源码javapublic final native void notify();public final native void ...public final void wait() throws InterruptedException {wait(0);}public final native void wait(long timeout) throws Interrupt...
  • 偏向、轻量级、重量级探究
  • Object的wait/notify/notifyAll方法解析
  • 【分布式】三种分布式的实现【原创】

    万次阅读 多人点赞 2021-03-02 22:55:58
    三种分布式的实现,Redis分布式,数据库,Zookeeper分布式,主要介绍的是Redis分布式
  • wait 和notify的应用场景在学习wait,notify之前首先需要解释java中wait()和notify()的应用场景。wait和notify提供了对多个线程之间的等待和通知操作。例如抓取站外多张图片通常会通过多个thread同时进行,但主线程...
  • 普通对象对象头:数组对象对象头:其中 Klass Word 是执行对象类型的指针,array length 是当对象为数组时用来存储数组长度的。MarkWord是机制的关键,单独说明下。1.1 MarkWord用来存储对象自身的运行时数据...
  • JAVA线程sleep()和wait()详解及实例sleep1.sleep是Thread的一个静态(static)方法。使得Runnable实现的线程也可以使用sleep方法。而且避免了线程之前相互调用sleep()方法,引发死锁。2.sleep()执行时需要赋予一个沉睡...
  • Thread类中把线程从running状态转化为非runnable状态有一个方法就是wait方法。wait方法是线程的等待状态。我们来看看wait方法简单运用下面是一个wait方法的代码packageThreadTest;/*** thread wait方法详解*@...
  • java 中的wait()和notify()

    2021-02-28 10:51:24
    java 中的wait()和notify()是实现condition variables的具体方法。教科书上的condition variables模型需要指定具体的变量,比如在生产者和消费者模型中的condition full, empty,分别表示由于buffer已满而造成生产者...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,747
精华内容 16,698
关键字:

wait放弃对象锁