线程的生命周期
新建(New)、就绪(Runnable)、执行(Running)、阻塞(Blocked)、死亡(Dead)
新建状态
当程序使用 new 关键字创建了一个线程之后,该线程就处于新建状态,此时仅由 JVM 为其分配内存,并初始化其成员变量的值。
就绪状态
当线程对象调用了 start()方法之后,该线程处于就绪状态。 Java 虚拟机会为其创建方法调用栈和程序计数器,等待调度运行。
运行状态
如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状态。
阻塞状态
阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。直到线程进入就绪状态,才有机会再次获得 cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
1.等待阻塞(o.wait->等待队列) 运行(running)的线程执行 o.wait()方法, JVM 会把该线程放入等待队列中。 2.同步阻塞(lock->锁池) 线程在获取对象的同步锁时,若该同步锁被别的线程占用,JVM会把该线程放入锁池中。 3.其他阻塞(sleep/join) 线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。 当 sleep()状态超时、 join()等待线程终止或者超时、或者 I/O处理完毕时,线程重新转入就绪状态。
线程死亡
1.正常结束, run()或 call()方法执行完成,线程正常结束。(包扩使用退出标志可控地退出线程和调用interrupt()方法)
interrupt() 1. 线程处于阻塞状态: 如使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时, 会使线程处于阻塞状态。当调用线程的 interrupt()方法时,会抛出 InterruptException 异常。 阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后 break 跳出循环状态,从而让 我们有机会结束这个线程的执行。 通常很多人认为只要调用 interrupt 方法线程就会结束,实 际上是错的, 一定要先捕获 InterruptedException 异常之后通过 break 来跳出循环,才能正 常结束 run 方法。 2. 线程未处于阻塞状态: 使用 isInterrupted()判断线程的中断标志来退出循环。当使用 interrupt()方法时,中断标志就会置 true,和使用自定义的标志来控制循环是一样的道理。 异常结束,线程抛出一个未捕获的 Exception 或 Error。
2.异常结束,线程抛出一个未捕获的 Exception 或 Error。
3.调用 stop(线程不安全,不推荐使用)。
类似突然关闭计算机电源,而不是按正常程序关机一样。thread.stop()调用之后,创建子线程的线程就会抛出 ThreadDeatherror 的错误,并且会释放子线程所持有的所有锁,可能会造成数据不一致。
JAVA实现多线程的方法
一. 继承Thread类
public class MyThread extends Thread { private String name; public MyThread(String name){ this.name = name; } public void run() { System.out.println(name+":is running!"); } } public class test{ public static void main(String[] args){ MyThread myThread1 = new MyThread("线程1"); MyThread myThread2 = new MyThread("线程2"); myThread1.start(); myThread2.start(); } }
二. 实现Runnable接口
如果自己的类已经extends另一个类,就无法直接extends Thread,此时,可以实现一个Runnable接口。
public class MyThread extends OtherClass implements Runnable { private String name; public MyThread(String name){ this.name = name; } public void run() { System.out.println(name+":is running!"); } } public class test{ public static void main(String[] args){ //为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例: MyThread myThread = new MyThread("我的线程"); Thread thread = new Thread(myThread); thread.start(); } }
原文:https://www.cnblogs.com/shijianchuzhenzhi/p/12943772.html