实现线程最简单的做法是从java.lang.Thread继承,然后覆盖其run()方法。必须调用start()方法来启动线程。对于Thread对象,虽然在用户程序看来可能没有对它的引用,但这并不会使它成为垃圾回收器要回收的对象(其他的对象若没有引用会被回收),因为Thread对象需要注册自己(start函数作用),所以实际上在某个地方存在对它的引用垃圾回收器只有在线程离开了run()并且死亡之后才会把它清理掉。


    yield()方法可以在run()中用来暗示作出让步,但机制并不保证它一定会被采纳。
 
    sleep()使线程休眠给定的毫秒数时间。使用时必须放在try块中,因为sleep()可能会在休眠期间被中断(比如对此线程调用interrupt()函数)。
 
    setPriority()和 getPriority()用来设置 或者 取得线程的优先权。注意优先级低的线程仅仅是执行的频率较低,不代表不会被执行,因此优先权不会导致死锁。
 
    可以再调用start()启动线程前调用setDaemon(true)把它设置为后台线程。如果程序里面没有非后台线程,那么程序会立即终止,即使还有后台线程在运行。后台线程创建的任何线程都会自动设置为后台线程。可以通过调用isDaemon()来判断某线程是否为后台线程。
 
    有线程A,B。如果在 线程A 内部调用了B.join()  ,那么 线程A 会被挂起,直至目标线程B 结束才恢复。如果join()带上了超时参数,就会在超时后返回。join()函数同样可以被interrupt()函数中断。
 
 
 
 
    也可以通过实现Runnable接口来达到目的。实现Runnable接口只需要实现run()方法。但对象具有Runnable接口,也仅仅只是表面他有run()方法而已,本身并不带有任何和线程有关的特性。因此要从Runnable对象产生线程,必须建立一个单独的Thread对象,并把实现的Runnable对象作为参数传递,并调用Thread对象的start()方法。还必须通过Thread.currentThread() 方法才能明确得到对此线程的引用。
 
 
    Java提供了关键字synchronized来解决共享资源竞争。要控制对共享资源的访问,先把它包装为一个对象,然后把所有要访问这个资源的方法标记为synchronized。一旦某个线程处于一个标记为synchronized的方法中,那么在这个线程从该方法返回之前,其他所有要调用类中标记为synchronized方法的线程都会被阻塞。每个对象都含有单一的锁,作为对象自身的一部分。当在对象上调用其任意的synchronized方法的时候,此对象都会被加锁,同一个对象的所有synchronized方法共享同一个锁,这能防止资源被多个线程同时访问。但同时,一个线程可以多次获得对象的锁,这允许在一个synchronized方法内调用另一个synchronized方法,显然只有首先获得了锁的线程才能允许继续获取多个锁。JVM会负责跟踪对象被加锁的次数。对于每个类,也有一个锁,作为类的一部分,这样synchronized static 方法可以在类的范围内防止对static数据的并发访问。
 
    线程之间的协作
    当一个线程在方法里调用wait()时,线程的执行将被挂起。如果接受毫秒数作为参数,表示在此期间暂停。不同的是wait()期间对象的锁是释放的,这意味着可以调用线程对象中的其他同步控制方法,而sleep()期间锁没有释放。可以通过notify()、notifyAll()、或者时间到期,从wait()恢复。如果不接受参数,wait()将无限等待下去,知道线程收到notify()、notifyAll()消息。
    wait()、notifyAll()、notify()是基类Object的一部分,因此只能在同步控制方法或者同步控制块里调用这些函数,而不是像sleep()那样属于Thread的一部分。
    synchronized(对象){

        临界区代码
    } 
那么对于public synchronized void add(int num)这种情况,意味着什么呢?其实这种情况,锁就是这个方法所在的对象。同理,如果方法是public  static synchronized void add(int num),那么锁就是这个方法所在的class。

 posted on 2012-11-30 14:31  husterchenji  阅读(168)  评论(0编辑  收藏  举报