Java线程生命周期

发表于:2017-7-12 10:05

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:博客

  线程在Java中占据着重要的位置,同时包含着很多的内容,从本文到同步、线程消息通知、线程安全集合类,再到线程池、线程调度,以及线程与I/O之间的关系等等,都值得认真研究一番。本文尝试归纳线程的生命周期,从线程的创建到线程管理这些基本内容。
  重要方法
  以下是线程生命周期中一些重要的方法,其中有些是已经过时,不建议使用的方法。
  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();
      }
  }
  实现Runnable接口
  这里用了一个经典的卖票的例子,但却是线程不安全的,因为自增或者自减操作本身不是原子性的,一旦出现线程竞争就会导致数据不一致,比如下面两个线程分别卖完票之后,居然都出现了剩余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。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号