java多线程常用方法_多线程--java多线程常用方法

http://blog.csdn.net/zuoluoboy/article/details/4034935#

常用的线程方法:sleep(),  join(),

yield(),  wait(), notify(),

notifyAll().

注意实现Runnable接口类的对象实例化的方式.

尽管线程对象的常用方法可以通过API文档来了解,但是有很多方法仅仅从API说明是无法详细了解的。

本来打算用一节的篇幅来把线程方法中一些重要的知识说完,但这样下来估计要很常的篇幅,可能要用好几节才能说把和线程方法相关的一些重要的知识说完。

首先我们接基础篇(二)来说明start()方法。

一个线程对象生成后,如果要产生一个执行的线程,就一定要调用它的start()方法.在介绍这个方法时不得不同时说明run方法.其实线程对

象的run方法完全是一个接口回调方法,它是你这个线程对象要完成的具体逻辑.简单说你要做什么就你在run中完成,而如何做,什么时候做就不需要你控制

了,你只要调用start()方法,JVM就会管理这个线程对象让它产生一个线程并注册到线程处理系统中。

从表面上看,start()方法调用了run()方法,事实上,start()方法并没有直接调用run方法.在JDK1.5以前

start()方法是本地方法,它如何最终调用run方法已经不是JAVA程序员所能了解的.而在JDK1.5中,原来的那个本地start()方法被

start0()代替,另个一个纯JAVA的start()中调用本地方法start0(),而在start()方法中做了一个验证,就是对一个全局变量

(对象变量)started做检验,如果为true,则start()抛出异常,不会调用本地方法start0(),否则,先将该变量设有true,然后

调用start0()。

从中我们可以看到这个为了控制一个线程对象只能运行成功一次start()方法.这是因为线程的运行要获取当前环境,包括安全,父线程的权限,

优先级等条件,如果一个线程对象可以运行多次,那么定义一个static

的线程在一个环境中获取相应权限和优先级,运行完成后它在另一个环境中利用原来的权限和优先级等属性在当前环境中运行,这样就造成无法预知的结果.简单说

来,让一个线程对象只能成功运行一次,是基于对线程管理的需要。

start()方法最本质的功能是从CPU中申请另一个线程空间来执行

run()方法中的代码,它和当前的线程是两条线,在相对独立的线程空间运行,也就是说,如果你直接调用线程对象的run()方法,当然也会执行,但那是

在当前线程中执行,run()方法执行完成后继续执行下面的代码.而调用start()方法后,run()方法的代码会和当前线程并发(单CPU)或并行

(多CPU)执行。

所以请记住一句话[调用线程对象的run方法不会产生一个新的线程,虽然可以达到相同的执行结果,但执行过程和执行效率不同。

[线程的interrupt()方法,interrupted()和isInterrupted()]

这三个方法是关系非常密切而且又比较复杂的,虽然它们各自的功能很清楚,但它们之间的关系有大多数人不是真正的了解。

先说interrupt()方法,它是实例方法,而它也是最奇怪的方法,在java语言中,线程最初被设计为"隐晦难懂"的东西,直到现在它的

语义不没有象它的名字那样准确。大多数人以为,一个线程象调用了interrupt()方法,那它对应的线程就应该被中断而抛出异常,事实中,当一个线程

对象调用interrupt()方法,它对应的线程并没有被中断,只是改变了它的中断状态。

使当前线程的状态变以中断状态,如果没有其它影响,线程还会自己继续执行。

只有当线程执行到sleep,wait,join等方法时,或者自己检查中断状态而抛出异常的情况下,线程才会抛出异常。

如果线程对象调用interrupt()后它对应的线程就立即中断,那么interrupted()方法就不可能执行。

因为interrupted()方法是一个static方法,就是说只能在当前线程上调用,而如果一个线程interrupt()后它已经中断了,那它又如何让自己interrupted()?

正因为一个线程调用interrupt()后只是改变了中断状态,它可以继续执行下去,在没有调用sleep,wait,join等法或自己抛

出异常之前,它就可以调用interrupted()来清除中断状态(还会原状)interrupted()方法会检查当前线程的中断状态,如果为

"被中断状态"则改变当前线程为"非中断状态"并返回true,如果为"非中断状态"则返回false,它不仅检查当前线程是否为中断状态,而且在保证当

前线程回来非中断状态,所以它叫"interrupted",是说中断的状态已经结束(到非中断状态了)isInterrupted()方法则仅仅检查线

程对象对应的线程是否是中断状态,并不改变它的状态。

目前大家只能先记住这三个方法的功能,只有真正深入到多线程编程实践中,才会体会到它们为什么是对象方法,为什么是类方法。

线程到底什么时候才被中断抛出InterruptedException异常,我们将在提高篇中详细讨论。

[sleep(),join(),yield()方法]

在现在的环节中,我只能先说明这些方法的作用和调用原则,至于为什么,在基础篇中无法深入,只能在提高篇中详细说明。

sleep()方法中是类方法,也就是对当前线程而言的,程序员不能指定某个线程去sleep,只能是当前线程执行到sleep()方法时,睡

眠指定的时间(让其它线程运行).事实上也只能是类方法,在当前线程上调用.试想如果你调用一个线程对象的sleep()方法,那么这个对象对应的线程如

果不是正在运行,它如何sleep()?所以只有当前线程,因为它正在执行,你才能保证它可以调用sleep()方法。

原则:[在同步方法中尽量不要调用线程的sleep()方法],或者简单说,对于一般水平的程序员你基本不应该调用sleep()方法。

join()方法,Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作,也就是在线程B中调用线程A对象的join()方法时,B必须等到A执行完成后才能执行.

原则:[join是测试其它工作状态的唯一正确方法],我见过很多人,甚至有的是博士生,在处理一项工作时如果另一项工作没有完成,说让当前工

作线程sleep(x),我问他,你这个x是如何指定的,你怎么知道是100毫秒而不是99毫秒或是101毫秒?其实这就是OnXXX事件的实质,我们不

是要等多长时间才去做什么事,而是当等待的工作正好完成的时候去做。

yield()方法也是类方法,只在当前线程上调用,理由同上。当一个线程抢到执行权后,执行到yield()方法后,就会放弃执行权,放弃本次分配到的时间片,其他线程就可以拿到执行权

了。原则:[不是非常必要的情况下,没有理

由调用它].调用这个方法不会提高任何效率,只是降低了CPU的总周期上面介绍的线程一些方法,基于(基础篇)而言只能简单提及.以后具体应用中我会结合

实例详细论述。

wait(),notify()(这两个不是静态方法)必须要与synchronized(Obj)一起使用,也就是wait,与notify只能在取得对象锁的时候才能调用。从语法角度来说就是wait(),

notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。

Thread.sleep()与wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。

notify()方法表示,当前的线程已经放弃对资源的占有,通知等待的线程来获得对资源的占有权,但是只有一个线程能够从wait状态中恢复,

然后继续运行wait()后面的语句;

notifyAll()方法表示,当前的线程已经放弃对资源的占有,通知所有的等待线程从wait()方法后的语句开始运行。

[wait(),notify()/notityAll()方法是普通对象的方法(Object超类中实现),而不是线程对象的方法]

[wait(),notify()/notityAll()方法只能在同步方法中调用]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值