线程对象

  每个线程都和类Thread的实例相关,有两种基本的使用Thread对象来创建并发应用的方法:

  • 直接控制线程的创建和管理,每次需要开始一个异步任务时简单地实例化Thread类。
  • 从你的程序中转移线程的管理,将应用的任务传递给一个执行程序。

  本章主要讨论Thread类。

定义并启动一个线程

  创建一个线程对象必须提供线程中执行的代码,实现的方法有两种:

  • 实现Runnable接口,Runnable接口定义了一个run方法,该方法中含有在线程中执行的方法,Runnable对象作为参数传递给Thread类的构造器来创建新的Thread实例,如下所示:
public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }
//以下主方法创利用定义的Runnable的实现类建类一个线程对象
    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}
  •  继承Thread类,Thread类自身是实现Runnable接口的,尽管其run方法不执行任何操作,一个类可以继承Thread类,覆写run方法,如下所示:
public class HelloThread extends Thread {
    public void run() {
        System.out.println("Hello from a thread!");
    }
    public static void main(String args[]) {
        (new HelloThread()).start();
    }

}

   两个例子中,调用Thread实例中的start方法的作用就是启动新创建的线程。

  对于这两种方法我们使用那种呢?第一种方法使用更为广泛一些,因为实现Runnable后不仅可以创建新的线程,而且还可以继承除Thread的其他类。而第二种用法在简单的应用中则更为快捷,但是不能再继承其他类。以下举例都用第一种方法,因为该方法更加灵活,更重要的是其适用于更高级的线程管理API。

用sleep方法暂停执行

  Thread.sleep方法会导致当前的线程暂停指定的时间。这个方法在需要将处理器时间交给其他线程或进程的时候比较有效。

  sleep方法由两个重载的版本,一个指定休眠的毫秒数,另外一个指定休眠的纳秒数,当然,时间不一定精确,计时是由底层的操作系统决定的,睡眠期间可以终止,因此任何时候,你都不要指望sleep方法能够暂停你指定的时间长度。

中断

  中断是指示一个线程停下当前所做的事情去做另外一件事,一个线程对于中断的反应是由程序员决定的,不过一般都是终止该线程。通过调用一个线程对象的interrupt方法,可以中断该线程,为了使中断机制正常运行,被中断的线程必须支持自身的中断。

支持中断  

  要使一个线程支持中断,则要在确保在线程接受到中断指示时从run方法返回,如果该线程经常调用一些抛出InterruptedException的方法,那么捕获InterruptedException后,就应该使用return语句返回,如果没有使用抛出中断异常的方法,则要使用定期使用Thread.interrupted方法判断该线程是否被中断,如果中断,使用return语句返回:

for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        //如果被中断,则返回
        return;
    }
}

中断状态标志

  中断机制是用一个内部的标志,叫做中断状态实现的,调用Thread.interrupt方法将设定该标志,当通过一个静态方法Thread.interrupted来检查中断状态时,中断状态会被清除,非静态方法isInterrupted,一个线程用来检查另外一个线程的中断状态的,该方法不会改变中断状态。

  在一个线程中,所有因抛出InterruptedException而返回的方法都会清除中断状态,但不排除之后立马会有其他线程设置其中断状态。

join方法

  join方法的使用允许一个线程等待另一个线程执行完毕,如果t是一个当前正在执行的Thread对象,则:

t.join();

  以上方法会让当前的线程暂停执行直到t执行完毕为止。join方法还有另外一个重载的版本,可以加入参数指定最长的等待时间,超过该时间后将不再等待。和sleep一样,其时间的准确性由系统而定,同时能对中断响应。