重要方法
以下是线程生命周期中一些重要的方法,其中有些是已经过时,不建议使用的方法。
public static native void sleep(long millis) throws InterruptedException; public synchronized void start() public void run() public void interrupt() public boolean isInterrupted() public final native boolean isAlive(); public final void join() //废弃方法,过时方法 public final void stop() public final void suspend() public final void resume() |
继承Thread类
public class ScheduleTask extends Thread{ public void run(){ System.out.println(Thread.currentThread().getName()); } public static void main(String[] args) { ScheduleTask t1 = new ScheduleTask(); ScheduleTask t2 = new ScheduleTask(); t1.start(); t2.start(); } } |
这里用了一个经典的卖票的例子,但却是线程不安全的,因为自增或者自减操作本身不是原子性的,一旦出现线程竞争就会导致数据不一致,比如下面两个线程分别卖完票之后,居然都出现了剩余99张票的情况,这就分明是错误的。如果要想修改的话可以将int类型修改为AtomicInteger原子类或者用synchronized这个关键字修饰自减整个操作。
public class SellTicket implements Runnable { //线程不安全的反例,因为每个卖票操作应该是原子的 private int tickets=100;//AtomicInteger @Override public void run() { while (tickets>0) { System.out.println(Thread.currentThread().getName()+" say :The tickets is remaining " + --tickets); } } public static void main(String[] args) { SellTicket sellTicket = new SellTicket(); Thread seller1 = new Thread(sellTicket); Thread seller2 =new Thread(sellTicket); seller1.start(); seller2.start(); } /** * 输出: * Thread-1 say :The tickets is remaining 99 * Thread-0 say :The tickets is remaining 99 * ... */ } |
当准备要运行程序代码时候,就调用start方法,这个方法会做一些准备工作之后调用线程内部的run方法。在start()方法被调用之后,新的thread可说是“活跃的(alive)”,可以通过isAlive()方法判断线程的状态,如果返回结果是true,则该线程已经被启动并且正在运行run()这个方法,否则该线程可能还没有启动或者已经被终结了。
线程终止
一且启动后,thread只能执行一个method;run()方法。这个method可以很复杂,它可以永远地执行下去,且它也可以调用其他method.无论如何,一旦run()方法完成了执行动作,thread也就必须完成它的执行动作。因此,终结thread的唯一办法就是安排run()方法完成。
1.线程的stop()方法,但是stop()方法有个固有的问题(内部的race condition),因此stop()方法已经被废除且不应该使用。
2.设定标记,通过判断外界标记条件是否符合要求来终止线程运行。
3.interrupt()方法,当你想终结thread的时候,通常会想立即地完成它的blocking method,此时可以使用Thread的interrupt()方法来中断任何的blocking method.但是此方法会带来一个问题就是,中断任何的blocked method 都会抛出InterruptedException.比如sleep()、wait()、join()方法等等,都是blocking method.
4.异常造成的终止,run()这个method不能抛出checked异常,但如同其他的Java method,它可以抛出unchecked异常。(这里简单说下:Checked exception 是在编译阶段的异常,强制检查,必须要catch的,比如IOException;unchecked exception分为Error和Runtime exception,是 runtime 阶段碰到的异常. 在编译的时候不需要检查 (checked),也无法检查的,比如NPE、ArrayIndexOutOfBoundsException等等.)如果run方法在运行时不能catch到运行时异常,也会造成线程的终止。
线程善后
一个完成run()方法的线程就是已经终结的,不再是活跃的(isAlive()方法会返回false)。一般来说,之后你就不应该再占据该thread的引用以便让该thread在终结时能够被同收。一个还要占据thread引用的场景就是要判别该线程是否已经完成工作,通过join()方法来完成。
join()方法经常用在想知道是否该线程已经完成,当调用该方法时,join()方法会被block住直到thread完成它的run()方法。如果thread已经完成它的
run()方法,join()方法就会立即返回,不再block。