几种方法的解释

Thread类中的方法

1、yield

public static native void yield();

该方法向线程调度器提示,当前线程(调用该方法的线程对象代表的线程)愿意让出处理器的使用权,但是线程调度器可能会忽视该提示。很少有适合使用该方法的地方。它可能在调试或者测试的时候,帮助重现由于竞争条件出现的bug。它还可能在设计并发控制结构的时候提供帮助,比如java.util.concurrent.locks包中的一些类。

2、sleep

public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;

该方法会让当前线程(调用该方法的线程对象代表的线程)睡眠指定的一段时间(暂时停止执行),但当前线程不会失去锁的拥有权(还会继续占用锁)。上述两个方法只是指定的睡眠时间精度不同。

3、start

public synchronized void start()

该方法会让当前线程(调用该方法的线程对象代表的线程)开始执行。JVM虚拟机会调用该线程的run()方法。对一个线程只能start()一次。

对同一个线程多次调用start()会抛出异常:java.lang.IllegalThreadStateException,即当前状态(start)不能调用start()方法。

但是可以多次调用线程的run()方法!

4、join

public final synchronized void join(long millis) throws InterruptedException
public final synchronized void join(long millis, int nanos) throws InterruptedException
public final void join() throws InterruptedException

该方法会让当前线程(调用该方法的线程,注意,这里并不是thread.join()中thread所表示的线程,而是方法thread.join()所在的线程)等待指定时间(如果为0,表示一直等到thread执行完),让join()方法的所属线程thread执行。 join()方法内部是调用wait()方法实现的。

Object类中的方法

1、wait

public final native void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException
public final void wait() throws InterruptedException

该方法会让当前线程(该方法调用所在的线程)进入等待状态,直到被该对象(wait()方法的this对象)的notify()或者notifyAll()唤醒,或者等待时间结束(wait(long timeout)中的timeout结束)。

当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时会释放对象的锁(暂时,wait(long timeout)超时时间到后还需要返还对象锁),此时其他线程可以访问该对象;这里隐含了一个条件就是:wait()方法只应该被拥有对象monitor的线程调用,即wiat()必须放在synchronized同步块中,否则会在抛出java.lang.IllegalMonitorStateException异常。

如果发生下面的4种事件中的任意一件,该线程就会从该对象的等待集中移除,重新加入线程调度。此后,它就会和其他线程一样去争夺该对象的锁,一旦获取了该对象的控制权,所有该对象的同步声明就会重新加载。

  • 其他线程触发了该对象的notify方法,那么该线程就可能会被唤醒(并不一定会唤醒,可能很多线程都wait该对象);

  • 其他线程触发了notifyAll方法;

  • 被其他线程中断(interrupt()方法)

  • 设定的等待时间已到。如果是wait(0)或者wait()则会一直等待直到唤醒。

正确使用wait()的方式如下:(等待应该总是发生在轮询中:waits should always occur in loops)

synchronized (obj) {
       while (condition does not hold)
               obj.wait(timeout);
           ... // Perform action appropriate to condition
}

如果当前线程在等待之前或者等待期间被其他线程打断(Thread.interrupt()),就会抛出InterruptedException异常。

2、notify

public final native void notify();
public final native void notifyAll();

notify()唤醒等待该对象monitor的单个线程。如果多个线程都在等待该对象monitor,那么被唤醒的线程是不固定的、任意的。被唤醒的线程并不会立即执行,而是等到当前线程放弃了该对象的锁。被唤醒的线程会和其他线程去竞争对该对象的同步操作。也就是说,被唤醒的线程仅仅是被唤醒去参与竞争,并不是唤醒了就开始执行。 该方法只应该被该对象的monitor的所有者线程调用。一个线程成为该对象的monitor的所有者有以下三种途径: ①执行该对象的同步的实例方法 ②执行一个同步块,并且该同步了该对象 ③对Class类型的对象,执行该类的一个同步的静态方法

常见问题

1、sleep和wait的区别

  • sleep是Thread类的方法,wait是Object类的方法;

  • sleep只是让线程休眠,与锁机制无关,不会释放锁(假如已经拥有锁),而wait则会让所在线程放弃锁。

  • wait和sleep都可以通过interrupt方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException

Last updated