精华内容
下载资源
问答
  • 使当前线程(即调用该方法线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。 例如有两个线程...

    1、sleep()

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

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

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


    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()方法只能使同优先级的线程有执行的机会。

    展开全文
  • wait和notify区别

    2020-12-13 23:01:22
    wait和notify区别 wait和notify都是Object中的方法 wait和notify执行前,线程都必须获得对象锁 wait的作用是使当前线程进行等待 notify的作用是通知其他等待当前线程的对象锁的线程

    wait和notify区别

    • wait和notify都是Object中的方法
    • wait和notify执行前,线程都必须获得对象锁
    • wait的作用是使当前线程进行等待
    • notify的作用是通知其他等待当前线程的对象锁的线程
    展开全文
  • 在说wait和notify之前先说明sleep和wait的区别

    【视频】
    【正文】

    sleep和wait

    sleep()方法让出硬件资源,但不释放锁。
    wait()方法既让出硬件资源,也释放锁。
    理解:通过锁,可以让程序员得以控制线程是否有机会去执行,但要注意,线程获得了锁,但不一定获得硬件资源(CPU时间片),如果该线程内有sleep()方法,则该线程虽然用有锁但已经让出了CPU使用权。
    当执行wait()方法时,当前线程不在是运行状态,处于等待状态,不仅要让出硬件资源(CPU),也要释放锁。
    获取到锁,不表示该线程就一直持有硬件资源。
    下面示例是sleep方法,线程A内执行了sleep()方法,则A线程一直持有锁,则线程B无法执行,线程C没有syncronized修饰,不参与锁的获取,可以执行。

    public class SyncDemo {
        public static void main(String[] args) throws InterruptedException {
            System.out.println("开始执行主线程");
            Object obj=new Object();
    
            new Thread(()->{
                synchronized (obj){
                    System.out.println("开始执行子线程A");
                    try {
                        //obj.wait(5000);
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("结束执行子线程A");
                }
            },"A").start();
            //保证线程A始终先执行
            Thread.sleep(1000);
            new Thread(()->{
                synchronized (obj){
                    System.out.println("执行子线程B");
                }
            },"B").start();
    
            new Thread(()->{
    
                System.out.println("执行子线程C");
    
            },"C").start();
        }
    }
    

    下面是sleep()方法执行结果:
    在这里插入图片描述
    下面是wait()方法,同样是以上的代码,只不过将线程A代码中的sleep()和wait()注释切换了。

    	obj.wait(5000);
        //Thread.sleep(5000);
    

    下图是wait()方法执行结果,A线程执行后,执行到wait,释放锁和资源,B线程得以执行,而A线程如果执行sleep(),则B线程要等A睡过5秒之后才会得到锁。
    在这里插入图片描述

    锁池和等待池

    所有抢夺锁的线程都会进入锁池;
    所有执行wait()方法的线程都会进入等待池。
    notify()方法随机将等待池中的一个线程转换进锁池。
    notifyAll()方法将等待池中所有线程都扔进锁池,即所有线程都被唤醒,参与锁的抢夺。

    展开全文
  • 在使用Lock之前,我们都使用Object 的wait和notify实现同步。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。 线程consumer 线程producer ...

     在使用Lock之前,我们都使用Object 的wait和notify实现同步的。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。

    线程consumer 线程producer
    synchronize(obj){ 
        obj.wait();//没东西了,等待 
    }
    synchronize(obj){ 
        obj.notify();//有东西了,唤醒 
    }

    有了lock后,世道变了,现在是:

    lock.lock(); 
    condition.await(); 
    lock.unlock();
    lock.lock(); 
    condition.signal(); 
    lock.unlock();

    为了突出区别,省略了若干细节。区别有三点:

    1. 1. lock不再用synchronize把同步代码包装起来;
    2. 2. 阻塞需要另外一个对象condition;
    3. 3. 同步和唤醒的对象是condition而不是lock,对应的方法是await和signal,而不是wait和notify。

    为什么需要使用condition呢?简单一句话,lock更灵活。以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),等待队列负责保存被阻塞的线程(condition完成)。

    通过查看ReentrantLock的源代码发现,condition其实是等待队列的一个管理者,condition确保阻塞的对象按顺序被唤醒。

    wait()和notify()必须在synchronized的代码块中使用 因为只有在获取当前对象的锁时才能进行这两个操作 否则会报异常 而await()和signal()一般与Lock()配合使用

    notify和notifyAll有什么区别

    notify():唤醒在此对象监视器上等待的单个线程。
    notifyAll():唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

    锁池和等待池

    锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
    等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中
    所以我们可以很容易看到这两者的区别了:

    如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
    当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
    优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
    综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

    转载于:https://www.cnblogs.com/aaron911/p/11043699.html

    展开全文
  • 基本差别: sleep是Thread类方法,wait是Object类定义方法 sleep方法可以在任何地方使用 wait方法只能在synchronized方法或 synchronized块中使用 最主要本质区别 ...notify和notifyal...
  • 在使用Lock之前,我们都使用Object 的wait和notify实现同步。举例来说,一个producer和consumer,consumer发现没有东西了,等待,producer生成东西了,唤醒。 线程consumer 线程producer ...
  • 在使用Lock之前,我们都使用Object 的wait和notify实现同步。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。 线程consumer 线程producer synchronize...
  • Java park&unpark 与 wait&notify的区别

    千次阅读 2020-08-19 09:02:18
    unpark是以确定单个线程【堵塞】【唤醒】线程,而notify是随机唤醒同一把锁对象线程 park不会释放锁资源,wait会释放锁资源 park&unpark可以先unpark(park后直接就唤醒了),而wait&notify不能提前...
  • 要深入了解这两个的区别,我们需要先了解线程的两个状态。一个是运行态,一个是冻结态。1.什么是运行态呢? 即同时具备cpu的执行资格执行权。也就是说这个线程有权被cpu执行并且此时正在被cpu执行。2.什么事冻结态...
  • Object wait 和notify 1、因为wait需释放锁,所以必须在synchronized中使用(没有锁时使用会抛出IllegalMonitorStateException) 2、notify也要在synchronized使用,并且应该指定对象 3、synchronized(),wait(),...
  • sleep,interrupt和wait,notify的区别

    千次阅读 2012-01-14 15:34:46
    sleep()方法是使线程停止一段时间方法。在sleep 时间间隔期满后,线程不一定... wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间
  • 在使用Lock之前,我们都使用Object 的wait和notify实现同步。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。 线程consumer 线程producer synchronize(obj){ ...
  • 作用java使用wait(),notify(),notifyAll()来进行线程之间通讯共同点:都是Java Object对象里面方法: wait()方法:如果对象调用了wait方法就会使持有该对象线程把该对象控制权交出去,然后处于等待状态。 ...
  • Object 类中 waitnotify 与 notifyAll 方法可以用来实现线程之间调度,比如在阻塞队列(BlockingQueue)实现中,如果队列为空,则所有消费者线程进行阻塞 ( wait ),如果某一个时刻队列中新添加了一个元素,则...
  • wait方法有三个重载方法 public final void wait() throws InterruptedException public final void wait() throws ...1.wait方法这三个重载方法都将调用wait(long timeout)这个方法,wait()方法等价于wait(0)
  • wait方法和notify方法的区别

    千次阅读 2019-04-26 15:16:30
    1.wait()sleep()的区别 wait()是Object类的方法,sleep()是Thread类的方法; 调用Object对象的wait方法,线程会放弃对象锁,进入等待此对象的等待锁定池;只有针对对象调用notify()方法后当前线程才进入对象锁定池...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,585
精华内容 634
关键字:

wait和notify的区别