`
MauerSu
  • 浏览: 513912 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java之yield(),sleep(),wait()区别详解

 
阅读更多
源:http://dylanxu.iteye.com/blog/1322066
评:
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()方法只能使同优先级的线程有执行的机会。

----------------------
源:http://bbs.csdn.net/topics/290056344
评:
wait()notify()是只用在同步块或者同步方法中的

当多个线程同时操作一个引用时,我们可以用synchronized 声明同步方法
或者 使用synchronized(obj){}代码块
保证引用的数据安全。

通过obj这把锁头决定 A 线程先操作  其他线程在锁池等待  等A结束交出锁头  ,其他线程再抢。

如果A在运行中被阻塞了:
1.是被wait()阻塞了,A会进入等待池,必须有其他线程唤醒A,A才能进入锁池,等待抢锁。
2.是被sleep()阻塞了,A会睡一会,但是锁头不交,醒了继续执行。
3.是被yield()阻塞了,A会让位,然后再抢,但是因为他自己拿着锁头呢,所以抢的人只有他一个,结果还是他运行。
-----------------------------
源:http://blog.csdn.net/xwygn/article/details/7200731
评:http://bbs.csdn.net/topics/10234892

sleep,interrupt和wait,notify的区别
sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)"醒来"的线程具有更高的优先级。 (b)正在运行的线程因为其它原因而阻塞。
  wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

但我还是不怎么明白,就跑去论坛上找文章,看到了下面这篇,讲的不错,收录下来。

下面是我原来在CJSDN论坛上看到的一个贴子,涉及到同步,wait(),notify()等概念的理解,我试着根据原来的一些回复和Think in Java上的相关概念将wait()和notify()这两个方法剖析了一下,欢迎指教.

问题如下:

file://分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!
public class ThreadA{

public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
                System.out.println("b is start....");
synchronized(b)//括号里的b是什么意思,起什么作用?
{
try
{
System.out.println("Waiting for b to complete...");
b.wait();//这一句是什么意思,究竟让谁wait?
                                System.out.println("waiting....");
}
catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}

}


class ThreadB extends Thread
{
int total;
public void run()
{
            System.out.println("ThreadB is running ....");
synchronized(this)
{   System.out.println("ThreadB is excuting for statement..");
for (int i=0;i<100 ;i++ )
{
total +=i;
                                System.out.println("total is "+total);
}
notify();
}
}
}

要分析这个程序,首先要理解notify()和wait(),为什么在前几天纪录线程的时候没有纪录这两个方法呢,因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,每个对象都有notify和wait的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.

再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是wait()和notify了.

按照Think in Java中的解释:"wait()允许我们将线程置入"睡眠"状态,同时又"积极"地等待条件发生改变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."

我们来解释一下这句话.
"wait()允许我们将线程置入"睡眠"状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的.那和sleep,suspend有什么区别呢?

区别在于"(wait)同时又"积极"地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放.
而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况下(sleep啊,suspend啊),这是不可能的.
但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个对象锁收回来的呀.wait什么?就是wait别人用完了还给我啊!
好,那怎么把对象锁收回来呢?
第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回.
第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来.哎,假如我设了1小时之后收回,别人只用了半小时就完了,那怎么办呢?*!当然用完了就收回了,还管我设的是多长时间啊.

那么别人怎么通知我呢?相信大家都可以想到了,notify(),这就是最后一句话"而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒"的意思了.
因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().

这个时候我们来解释上面的程序,简直是易如反掌了.

synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行.

------------------------------------

分享到:
评论

相关推荐

    java+多线程+同步详解源代码学习

    Java多线程与同步是Java编程中的核心概念,它们在构建高效、响应迅速的应用程序时起着至关重要的作用。在大型系统开发中,多线程技术使得程序能够同时执行多个任务,提高系统的并发性,而同步机制则确保了在多线程...

    详解Java中的线程让步yield()与线程休眠sleep()方法

    本文将详细解析Java中的线程让步方法`yield()`以及线程休眠方法`sleep()`,并与线程等待的`wait()`方法进行对比。 首先,线程让步`yield()`方法的主要作用是让当前线程主动放弃执行权,让其他处于就绪状态且具有...

    Java多线程编程详解

    ### Java多线程编程详解 #### 一、线程同步机制 在Java多线程编程中,线程同步是一项至关重要的技术,它主要用于解决多线程环境中的资源共享问题。由于同一进程中的多个线程共享同一片内存空间,这就意味着它们...

    Java多线程详解(超详细)_狂神说笔记完整版_项目代码_适合小白随课程学习

    Java多线程详解 在Java编程中,多线程是一种重要的技术,它使得程序能够同时执行多个任务,提高系统的效率和响应性。本教程将详细讲解Java中的多线程概念,包括线程的创建、状态、同步以及高级主题,旨在帮助初学者...

    Java 线程详解

    Java 线程详解 在 Java 编程语言中,线程是一种基本的编程单元,它允许开发者在一个程序中执行多个任务。线程是轻量级的进程,它可以与其他线程共享同一个进程的资源。线程的使用可以提高程序的效率和响应速度。 ...

    Java高并发编程详解:多线程与架构设计 (Java核心技术系列)

    《Java高并发编程详解:多线程与架构设计》是一本深入探讨Java中多线程编程和并发架构的书籍,适合Java开发者和架构师阅读。本书分为四个部分,旨在帮助读者掌握Java并发的核心技术和设计原则。 第一部分是多线程...

    java 多线程详解

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,从而提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。这篇博文详细介绍了这两种方法以及它们之间的差异。 1....

    Java软件开发实战 Java基础与案例开发详解 12-2 线程的生命周期 共10页.pdf

    5. **TIMED_WAITING(超时等待)**:线程处于有限期等待状态,等待另一个线程执行依赖于指定等待时间的操作,例如调用`Object.wait(long timeout)`、`Thread.join(long timeout)`或`Thread.sleep(long millis)`等...

    Java多线程编程深入详解.rar

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程可以通过继承Thread类或实现Runnable接口来实现。下面我们将深入探讨Java多线程编程的...

    JAVA多线程编程详解-详细操作例子

    本主题将深入探讨“JAVA多线程编程详解-详细操作例子”,结合提供的资源,我们可以从以下几个方面进行学习: 1. **线程的基本概念**: 线程是程序执行的最小单位,一个进程可以有多个线程。在Java中,可以通过实现...

    Java多线程超级详解(看这篇就足够了).pdf

    Java提供了多种控制线程状态的方法,如`start()`启动线程,`run()`定义线程要执行的任务,`yield()`放弃当前CPU时间片,`join()`使线程等待其他线程完成,`sleep(long milliseconds)`让线程休眠指定时间,`wait()`让...

    java线程详解

    ### Java线程详解 #### 一、扩展`java.lang.Thread`类 在Java中实现多线程的一个方式是通过继承`java.lang.Thread`类。这种方式简单直观,但也有一定的局限性,比如不能再次继承其他类。 **示例代码**: ```java...

    java线程与并行(主要讲解java的nio包某些内容)

    ### Java线程与并行详解 #### 一、Java线程基础 在Java中,**线程**是一种轻量级的进程,它允许一个程序同时执行多个任务,从而提高程序的执行效率。Java从1.0版本开始就支持多线程编程,并在后续版本中不断完善。...

    Java线程培训资料

    ### Java线程培训资料知识点详解 #### 一、Java线程基本概念 1. **如何编写与启动线程** - **方式一:继承Thread类** ```java class MyThread extends Thread { @Override public void run() { // 业务逻辑 ...

    java线程学习资料

    ### Java线程学习资料知识点详解 #### 一、实现线程的方法及区别 Java中实现多线程主要有两种方式:**继承Thread类**与**实现Runnable接口**。 1. **继承Thread类**: - 创建一个新的类继承自`Thread`类,并重写...

    2020老杜最新Java零基础进阶视频教程-多线程课件

    Java提供了多种线程控制方法,如`sleep()`, `join()`, `yield()`, `interrupt()`, 和 `isInterrupted()`等,用于控制线程的执行顺序和暂停。 6. 线程同步 为了防止多个线程同时访问共享资源导致数据不一致,Java...

    java线程与模式总结

    Java中的线程机制是其一大亮点之一,它直接支持线程级别的并发处理。线程相比于进程具有创建成本低、上下文切换快等优势,这使得Java在处理高并发场景时能够表现出色。然而,线程的使用对开发者提出了较高的要求,...

Global site tag (gtag.js) - Google Analytics