通过继承Thread类实现多线程

  1. public class ThreadTest extends Thread{
  2. public ThreadTest(){
  3. System.out.println(this.getName());
  4. }
  5. /**
  6. * 线程的线程提
  7. */
  8. @Override
  9. public void run() {
  10. System.out.println(this.getName()+"线程开始");
  11. for(int i=0;i<10;i++){
  12. System.out.println(this.getName()+" "+i);
  13. }
  14. System.out.println(this.getName()+"线程结束");
  15. }
  16. public static void main(String[] args) {
  17. System.out.println("主线程开始");
  18. ThreadTest threadTest_1=new ThreadTest();
  19. //启动线程
  20. threadTest_1.start();
  21. ThreadTest threadTest_2=new ThreadTest();
  22. //线程启动
  23. threadTest_2.start();
  24. System.out.println("主线程结束");
  25. }
  26. }

image.png
缺点:不能从其他类继承了

通过实现Runnable接口实现多线程

  1. public class ThreadTest_2 implements Runnable{
  2. public ThreadTest_2(){
  3. System.out.println(Thread.currentThread().getName());
  4. }
  5. /**
  6. * 线程体方法
  7. */
  8. @Override
  9. public void run() {
  10. System.out.println(Thread.currentThread().getName()+"线程开始");
  11. for(int i=0;i<10;i++){
  12. System.out.println(Thread.currentThread().getName()+" "+i);
  13. }
  14. System.out.println(Thread.currentThread().getName()+"线程结束");
  15. }
  16. public static void main(String[] args) {
  17. System.out.println("主线程开始");
  18. ThreadTest_2 threadTest_2=new ThreadTest_2();
  19. //threadTest_2.start(); //这种写法是错的,还不是线程对象,没有start()方法
  20. Thread t1=new Thread(threadTest_2);
  21. t1.start();
  22. Thread t2=new Thread(new ThreadTest_2());
  23. t2.start();
  24. System.out.println("主线程结束");
  25. }
  26. }

image.png

线程的执行流程

image.png

线程的生命周期

image.png
一个线程对象在它的生命周期内,需要经历 5 个状态
新生状态(New) :
用 new 关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线 程有自己的内存空间,通过调用 start 方法进入就绪状态。

就绪状态(Runnable) :
处于就绪状态的线程已经具备了运行条件,但是还没有被分配到 CPU,处于“线程就 绪队列”,等待系统为其分配 CPU。就绪状态并不是执行状态,当系统选定一个等待执行 的 Thread 对象后,它就会进入执行状态。一旦获得 CPU,线程就进入运行状态并自动调 用自己的 run 方法。有 4 中原因会导致线程进入就绪状态 :

  1. 新建线程:调用 start()方法,进入就绪状态;
  2. 阻塞线程:阻塞解除,进入就绪状态;
  3. 运行线程:调用 yield()方法,直接进入就绪状态;
  4. 运行线程:JVM 将 CPU

运行状态(Running):
在运行状态的线程执行自己 run 方法中的代码,直到调用其他方法而终止或等待某资 源而阻塞或完成任务而死亡。如果在给定的时间片内没有执行结束,就会被系统给换下来回 到就绪状态。也可能由于某些“导致阻塞的事件”而进入阻塞状态。

阻塞状态(Blocked) :
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)。有 4 种原因 会导致阻塞:

  1. 执行 sleep(int millsecond)方法,使当前线程休眠,进入阻塞状态。当指定的时
    间到了后,线程进入就绪状态。
  2. 执行 wait()方法,使当前线程进入阻塞状态。当使用 nofity()方法唤醒这个线程后,
    它进入就绪状态。
  3. 线程运行时,某个操作进入阻塞状态,比如执行 IO 流操作(read()/write()方法本
    身就是阻塞的方法)。只有当引起该操作阻塞的原因消失后,线程进入就绪状态。
  4. join()线程联合: 当某个线程等待另一个线程执行结束后,才能继续执行时,使用
    join()方法

死亡状态(Terminated) :
死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有两个。一个是正常运行的线程完成了它 run()方法内的全部工作; 另一个是线程被强制终止,如通过执行 stop() 或 destroy()方法来终止一个线程(注:stop()/destroy()方法已经被 JDK 废弃,不推荐使用 )
当一个线程进入死亡状态以后,就不能再回到其它状态了。