结合多本著作和个人开发经验,整理Java多线程入门手册(3)

上一篇 / 下一篇  2023-02-03 10:54:01

  设置线程名
  实现类:
  public class RunnableImpl implements Runnable{
      @Override
      public void run() {
          // 输出10以内偶数
          for (int i = 0; i < 10; i++) {
              if (i % 2 == 0){
                  // 获取当前线程
                  Thread thread = Thread.currentThread();
                  // 获取线程名
                  String threadName = thread.getName();
                  System.out.println(threadName + "===>" + i);
              }
          }
      }
  }
  测试类:
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、创建实现类对象
          RunnableImpl runnable = new RunnableImpl();
          // 2、 创建线程对象,并指定线程名
          Thread t1 = new Thread(runnable, "线程1");
          // 3、启动线程
          t1.start();
          System.out.println(Thread.currentThread().getName() + "主线程");
      }
  }
  运行结果:
  或者通过setName()方法设置线程名:
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、创建实现类对象
          RunnableImpl runnable = new RunnableImpl();
          // 2、 创建线程对象,不指定名字
          Thread t1 = new Thread(runnable);
          // 设置线程名
          t1.setName("线程1");
          // 3、启动线程
          t1.start();
          System.out.println(Thread.currentThread().getName() + "主线程");
      }
  }
  如果不设置线程名,默认为【"Thread-" + nextThreadNum()】,nextThreadNum方法使用 threadInitNumber静态变量,默认从0开始,每次+1。
  不设置线程名运行效果如下:
  sleep方法
  sleep方法可以让线程阻塞指定的毫秒数。时间到了后,线程进入就绪状态。sleep可用来研模拟网络延时,倒计时等。每一个对象都有一个锁,sleep不会释放锁,锁的概念后边会详细讲解
  实现类:
  public class RunnableImpl implements Runnable{
      @Override
      public void run() {
          // 输出10以内偶数
          for (int i = 0; i < 10; i++) {
              if (i % 2 == 0){
                  try {
                      // 休眠1秒
                      Thread.sleep(1000);
                      System.out.println(Thread.currentThread().getName() + "===>" + i);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
      }
  }
  测试类:
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、创建实现类对象
          RunnableImpl runnable = new RunnableImpl();
          // 2、 创建线程对象,不指定名字
          Thread t1 = new Thread(runnable,"线程1");
          // 3、启动线程
          t1.start();
      }
  }
  运行结果:
  "善用"sleep年入百万不是梦:
  yield方法
  提出申请释放CPU资源,至于能否成功释放取决于JVM决定,调用yield()方法后,线程仍然处于RUNNABLE状态,线程不会进入阻塞状态,保留了随时被调用的权利
  实现类:
  public class RunnableImpl implements Runnable{
      @Override
      public void run() {
          System.out.println(Thread.currentThread().getName() + "开始执行");
          Thread.yield();
          System.out.println(Thread.currentThread().getName() + "执行结束");
      }
  }
  测试类:
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、创建实现类对象
          RunnableImpl runnable = new RunnableImpl();
          // 2、 创建线程对象,不指定名字
          Thread t1 = new Thread(runnable,"线程1");
          Thread t2 = new Thread(runnable,"线程2");
          // 3、启动线程
          t1.start();
          t2.start();
      }
  }
  运行结果:
  第五次执行是线程2执行开始结束后输出的线程1开始结束,这就说明CPU并没有切换到别的线程,说明并没有释放CPU资源。
  join方法
  将当前的线程挂起,当前线程阻塞,待其他的线程执行完毕,当前线程才能执行,可以把join()方法理解为插队,谁插到前面,谁先执行。
  在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束了。主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,join()方法比较合适这个场景。
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、lambda创建线程
          Thread t1 = new Thread(() -> {
              for (int i = 0; i < 5; i++) {
                  try {
                      // 模拟耗时操作
                      Thread.sleep(1000);
                      System.out.println(Thread.currentThread().getName() + "join方法===>" + i);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
          });
          // 2、 启动线程
          t1.start();
          try {
              // t1调用join 方法
              t1.join();
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
          System.out.println("main线程");
      }
  }
  运行结果:
  设置优先级
  改变、获取线程的优先级。Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。线程的优先级用数据表示,范围1~10。线程的优先级高只是表示他的权重大,获取CPU执行权的几率大。先设置线程的优先级,在执行start()方法。
  public class RunnableMain {
      public static void main(String[] args) {
          // 1、lambda创建线程
          Thread t1 = new Thread(() -> {
              System.out.println(Thread.currentThread().getName() + "线程优先级" + Thread.currentThread().getPriority());
          },"线程1");
          Thread t2 = new Thread(() -> {
              System.out.println(Thread.currentThread().getName() + "线程优先级" + Thread.currentThread().getPriority());
          },"线程2");
          // 2、设置线程优先级
          t1.setPriority(1);
          t2.setPriority(10);
          // 3、 启动线程
          t1.start();
          t2.start();
          System.out.println("main线程");
      }
  }
  结束线程
  JDK提供的【stop()、destroy()】两种方法已废弃,不推荐再使用。推荐线程自动停止下来,就比如上边的所有案例,都是执行完了run方法中的所有代码之后线程就自然结束了。如果线程需要循环执行,建议使用一个标识位变量进行终止,当flag=false时,则终止线程运行
  比如:定义一个名为【线程1】的子线程,当主线程执行3次循环之后,线程1停止运行
  实现类:
  public class RunnableImpl implements Runnable{
      // boolean变量标记是否需要继续执行
      private boolean flag = true;
      public boolean isFlag() {
          return flag;
      }
      public void setFlag(boolean flag) {
          this.flag = flag;
      }
      @Override
      public void run() {
          // 循环执行,flag为false时停止
          while (flag) {
              System.out.println(Thread.currentThread().getName() + "正在运行");
          }
      }
  }
  测试类:
  public class RunnableMain {
      public static void main(String[] args) {
          RunnableImpl runnable = new RunnableImpl();
          Thread t1 = new Thread(runnable, "线程1");
          t1.start();
          for (int i = 0; i < 5; i++) {
              System.out.println("主线程====》" + i);
              // 当循环三次时
              if(i == 3) {
                  // 设置flag值为false
                  runnable.setFlag(false);
              }
          }
      }
  }
  总结
  ·掌握多线程的使用场景和术语
  · 熟练创建和启动线程
  · 掌握线程状态和状态之间转换
  · 掌握Thread类中的常用方法如:join、sleep、yield等

TAG: Java java 多线程

 

评分:0

我来说两句

Open Toolbar