【Java】Thread详解

🍒前言

本文将从以下几方面来展开对Thread的介绍。

1.线程创建 2.线程中断 3.线程等待 4.线程休眠

在前面的文章中,已经总结了关于Thread的一些理解。

在阅读本文之前,最好对其有一些基础的了解。

文章链接: 【JavaSE】进程是什么?

文章链接: 【JavaSE】初识线程,线程与进程的区别

文章链接: 【JavaSE】Thread类中run和start的区别

文章目录

  • 🍒前言
  • 🍇线程的创建
    • 🍐1.继承 Thread 类
    • 🍐2.实现Runnable接口
    • 🍐3.匿名内部类
    • 🍐4.匿名内部类创建 Runnable ⼦类对象
    • 🍐5.lambda 表达式创建 Runnable ⼦类对象
    • 🍎线程中断
      • 🥝1.自己设定条件
        • **缺点**
        • 🥝2.使用interrupt和isInterrupted方法
        • 🍆线程等待
        • ✍线程休眠

          🍇线程的创建

          🍐1.继承 Thread 类

          class MyThread extends Thread{ @Override
              public void run() { while (true){ System.out.println("hello thread");
                      try { Thread.sleep(1000);
                      } catch (InterruptedException e) { throw new RuntimeException(e);
                      }
                  }
              }
          }
          public class demo1 { public static void main(String[] args) throws InterruptedException { Thread t = new MyThread();
                  t.start();
                  while (true){ System.out.println("hello main");
                      Thread.sleep(1000);
                  }
              }
          }
          

          🍐2.实现Runnable接口

          class MyRunnable implements Runnable{ @Override
              public void run() { while (true){ System.out.println("hello thread2");
                      try { Thread.sleep(1000);
                      } catch (InterruptedException e) { throw new RuntimeException(e);
                      }
                  }
              }
          }
          public class demo2 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new MyRunnable());
                  t.start();
                  while (true){ System.out.println("hello main2");
                      Thread.sleep(1000);
                  }
              }
          }
          

          🍐3.匿名内部类

          public class demo3 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(){ @Override
                      public void run() { while (true){ System.out.println("hello thread3");
                              try { Thread.sleep(1000);
                              } catch (InterruptedException e) { throw new RuntimeException(e);
                              }
                          }
                      }
                  };
                  t.start();
                  while (true){ System.out.println(" hello main");
                      Thread.sleep(1000);
                  }
              }
          }
          

          🍐4.匿名内部类创建 Runnable ⼦类对象

          public class demo4 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread((Runnable) () ->{ while (true){ System.out.println("hello thread4");
                         try { Thread.sleep(1000);
                         } catch (InterruptedException e) { throw new RuntimeException(e);
                         }
                     }
                  });
                  t.start();
                  while (true){ System.out.println(" hello main4");
                      Thread.sleep(1000);
                  }
              }
          }
          

          🍐5.lambda 表达式创建 Runnable ⼦类对象

          public class demo5 { public static void main(String[] args)  { Thread t = new Thread(()->{ while (true){ System.out.println("hello thred5");
                        try { Thread.sleep(1000);
                        } catch (InterruptedException e) { throw new RuntimeException(e);
                        }
                    }
                  });
                  t.start();
                  while (true){ System.out.println(" hello main5");
                      try { Thread.sleep(1000);
                      } catch (InterruptedException e) { throw new RuntimeException(e);
                      }
                  }
              }
          }
          

          🍎线程中断

          终止线程,在Java中所有的终止程序都只是“提醒,建议”。真正的是否结束都是由线程本体 自己决定的。

          在系统原生的线程中,是有办法让别的线程强制终止的,但这种设定不太好,所以Java没有采纳

          主要原因还是线程之间的调度是随机的。

          🥝1.自己设定条件

          之所以可以结束,是因为thread线程外面写了isRunning这样的条件,所以才能控制

          如果thread代码不这样写,那么thread都会继续执行,不会在意外面的条件

          最终决定权还是在thread手中。

           private static boolean isRunning = true;
              public static void main(String[] args) { Thread thread  = new Thread(()->{ while (isRunning){//自己书写条件控制线程的结束
                             System.out.println("hello thread");
                             try { Thread.sleep(1000);
                             } catch (InterruptedException e) { throw new RuntimeException(e);
                             }
                         }
                 });
                 thread.start();
                  try { Thread.sleep(3000);
                      //三秒之后  
                  } catch (InterruptedException e) { throw new RuntimeException(e);
                  }
                  isRunning = false;
                  //三秒之后设置 条件 终止线程
                  System.out.println("end Thread");
              }
          

          运行结果如下

          缺点

          🥝2.使用interrupt和isInterrupted方法

           public static void main(String[] args) throws InterruptedException { Thread t  = new Thread(()->{ // t.isInterrupted();
                     while (!Thread.currentThread().isInterrupted()){ System.out.println("hello thead");
                         try { Thread.sleep(1000);
                         } catch (InterruptedException e) { throw new RuntimeException(e);
                         }
                     }
                  });
                  t.start();
                  Thread.sleep(3000);
                  
                  t.interrupt();
              }
          

          运行程序

          发现3s之后,线程确实是结束了。但是是以抛出异常中断的情况结束,

          这样会使结果不那么美观。那么接下来就要解决这样的问题。

          解决方法

          我们不抛出异常,而是打印出异常。

          继续运行,看看结果是怎样的。

          我们可以看到结果中,打印出了异常,而线程并没有结束

          我们确确实实使用了interrupt方法,使标志位修改成了true了,那为什么线程还会继续执行呢?

          🍆线程等待

          因为线程是随机调度的,为了解决这样的问题,从而引入了线程等待。

          使用join()

           public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ for (int i = 0; i < 3; i++) { System.out.println("hello t1");
                          try { Thread.sleep(1000);
                          } catch (InterruptedException e) { throw new RuntimeException(e);
                          }
                      }
                  });
                  Thread t2 = new Thread(()->{ for (int i = 0; i < 3; i++) { System.out.println("hello t2");
                          try { Thread.sleep(1000);
                          } catch (InterruptedException e) { throw new RuntimeException(e);
                          }
                      }
                  });
                  t1.start();
                  t2.start();
                  t1.join();//加入条件
                  t2.join();//
                  System.out.println("end main");
              }
          

          运行结果如下

          main线程调用t1.join() t2.join(),t1 t2 继续执行 main线程等待

          t1和t2谁先结束,这是未知的

          而t1 和 t2 比main先结束,这是已知的。

          如果想要定义t1和t2的先后结束顺序

          就在对应的t1或t2线程内调用join()方法

          join还有一个带参数的方法

          不带参数的join方法就是所谓的“死等”

          ✍线程休眠

          线程休眠sleep控制的是“线程休眠的时间”,而是不是“两个代码执行的间隔时间”

          举例

           public static void main(String[] args) throws InterruptedException { System.out.println(System.currentTimeMillis());
                  Thread.sleep(1000);
                  System.out.println(System.currentTimeMillis());
              }
          

          由打印结果可以看出,这里并不是精准的1000,

          此处sleep是指线程阻塞的时间,在这个时间段内是无法抢占CPU的执行权的

          而时间结束,线程由阻塞状态变为就绪状态

          但这并不意味着它立即就能到CPU上去执行。

          以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞