首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的!

  在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。
  要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。可通过这种方法实现多个线程的资源共享。
  线程的生命周期:
  1.新建状态(New):用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存
  2.绪状态(Runnable):当一个线程创建了以后,其他的线程调用了它的start()方法,该线程进入了绪状态。处于这个状态的 线程位于可运行池中,等待获得CPU的使用权
  3.运行状态(Running): 处于这个状态的线程占用CPU,执行程序的代码
  4.阻塞状态(Blocked): 当线程处于阻塞状态时,java虚拟机不会给线程分配CPU,直到线程重新进入绪状态,它才有机会转到 运行状态。
  阻塞状态分为三种情况:
  1)、 位于对象等待池中的阻塞状态:当线程运行时,如果执行了某个对象的wait()方法,java虚拟机回把线程放到这个对象的等待池中
  2)、 位于对象锁中的阻塞状态,当线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他的线程占用,JVM会把这个线程放到这个对象的琐池中。
  3)、 其它的阻塞状态:当前线程执行了sleep()方法,或者调用了其它线程的join()方法,或者发出了I/O请求时,会进入这个状态中。
  一、创建并运行线程
  当调用start方法后,线程开始执行run方法中的代码。线程进入运行状态。可以通过Thread类的isAlive方法来判断线程是否处于运行状态。当线程处于运行状态时,isAlive返回true,当isAlive返回false时,可能线程处于等待状态,也可能处于停止状态。
  二、挂起和唤醒线程
  一但线程开始执行run方法,会一直到这个run方法执行完成这个线程才退出。但在线程执行的过程中,可以通过两个方法使线程暂时停止执行。这两个方法是suspend和sleep。在使用suspend挂起线程后,可以通过resume方法唤醒线程。而使用sleep使线程休眠后,只能在设定的时间后使线程处于绪状态(在线程休眠结束后,线程不一定会马上执行,只是进入了绪状态,等待着系统进行调度)。
  虽然suspend和resume可以很方便地使线程挂起和唤醒,但由于使用这两个方法可能会造成一些不可预料的事情发生,因此,这两个方法被标识为deprecated(弃用)标记,这表明在以后的jdk版本中这两个方法可能被删除,所以尽量不要使用这两个方法来操作线程。
  三、终止线程的三种方法
  有三种方法可以使终止线程。
  1.  使用退出标志,使线程正常退出,也是当run方法完成后线程终止。
  2.  使用stop方法强行终止线程(线程中调用了阻塞代码)(这个方法不推荐使用,因为stop是依靠抛出异常来结束线程的,也可能发生不可预料的结果)。如果没有调用阻塞代码,可以正常结束线程。
  3.  使用interrupt方法中断线程(线程中调用了阻塞代码)(其实这种方法也是通过抛出异常来结束线程的)。如果没有调用阻塞代码,可以通过判断线程的中断标志位来介绍线程。
  线程的几个方法:
  join():等待此线程死亡后再继续,可使异步线程变为同步线程
  interrupt():中断线程,被中断线程会抛InterruptedException
  wait():等待获取锁:表示等待获取某个锁执行了该方法的线程释放对象的锁,JVM会把该线程放到对象的等待池中。该线程等待其它线程唤醒
  notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程,JVM从对象的等待池中随机选择一个线程,把它转到对象的锁池中。使线程由阻塞队列进入绪状态
  sleep():让当前正在执行的线程休眠,有一个用法可以代替yield函数——sleep(0)
  yield():暂停当前正在执行的线程对象,并执行其他线程。也是交出CPU一段时间(其他同样的优先级或者更高优先级的线程可以获取到运行的机会)