java-并发-线程对象
浏览以下内容前,请点击并阅读 声明
线程对象
每个线程都和类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.interrupt
ed来检查中断状态时,中断状态会被清除,非静态方法isInterrupted,一个线程用来检查另外一个线程的中断状态的,该方法不会改变中断状态。
在一个线程中,所有因抛出InterruptedException
而返回的方法都会清除中断状态,但不排除之后立马会有其他线程设置其中断状态。
join方法
join方法的使用允许一个线程等待另一个线程执行完毕,如果t是一个当前正在执行的Thread对象,则:
t.join();
以上方法会让当前的线程暂停执行直到t执行完毕为止。join方法还有另外一个重载的版本,可以加入参数指定最长的等待时间,超过该时间后将不再等待。和sleep一样,其时间的准确性由系统而定,同时能对中断响应。