JavaEE之线程(3)_线程的开始、中断、等待、休眠线程、线程的状态

前言

在本栏的上一节(https://blog.csdn.net/2301_80653026/article/details/138500558),我们重点讲解了五种不同的创建线程的方式,我们还介绍了Tread类的常见构造方法和常见属性,在这一节中我们将会继续介绍Tread类。


一、启动一个线程 start( )

在上一节我们讲解了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。比如:

  1. 覆写 run 方法是提供给线程要做的事情的指令清单
  2. 线程对象可以认为是把 李四、王五叫过来了
  3. 而调用 start( ) 方法,就是喊一声:"行动起来!",线程才真正独立去执行了

调用 start 方法, 才真的在操作系统的底层创建出一个线程。
Thread类中run和start的区别:

作用功能不同:

1. run方法的作用是描述线程具体要执行的任务;

2. start方法的作用是真正的去申请系统线程

.运行结果不同:

1. run方法是一个类中的普通方法,主动调用和调用普通方法一样,会顺序执行一次;

2. start调用方法后, start方法内部会调用Java 本地方法(封装了对系统底层的调用)真正的启动线程,并执行run方法中的代码,run 方法执行完成后线程进入销毁阶段

参考示例代码:

bash 复制代码
/**
 * @author Zhang
 * @date 2024/4/2915:16
 * @Description:
 */

//创建一个类,继承自Thread
class  MyThread extends  Thread{
    //这个方法就是线程的入口方法
    @Override
    public void run() {
       // System.out.println("hello Thread");
       
        while(true){
            System.out.println("hello threat");
            try {
                Thread.sleep(1000);  //休眠1000毫秒
                /**
                 * 此处必须try catch,不能throws
                 * 在这个代码中重写的是父类的run,父类的run没有throws,因此,子类方法也就不能有throws
                 */
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

//创建线程
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        //start 和run都是Threat的成员
        //run只是描述了线程的入口(线程要做生么任务)
        //start 则是真正调用了系统API,在系统中创建线程,让线程再调用run
        t.start();

         while(true){
         System.out.println("hello main");
         Thread.sleep(1000);  //休眠1000毫秒
         }
    }
}

二、中断一个线程

停止一个线程主要有以下两种方式:

2.1 通过共享的标记来进行沟通

参考实例代码:

bash 复制代码
/**
 * @author Zhang
 * @date 2024/5/415:58
 * @Description:
 */
public class Demo8 {
    private  static  boolean isQuit = false;  //成员变量
    public static void main(String[] args) throws InterruptedException {
       //  boolean isQuit = false; 不能使用局部 变量
        Thread t=  new Thread(()->{
            while(!isQuit){
                //
                System.out.println("线程工作中");
                //此处的打印可以替换成任意的逻辑来表示逻辑的实际工作内容
                  try {
                       Thread.sleep(1000);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
            System.out.println("线程作完毕");
        });
        t.start();
        Thread.sleep(5000);
        isQuit = true;
        System.out.println("设置 isQuit 为 true");

    }
}

2.2 调用interrupt( )方法来通知

使用 Thread.interrupted() 或Thread.currentThread().isInterrupted() 代替自定义标志位。其中,Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记。

使用 thread 对象的 interrupted() 方法通知线程结束的代码参考实例:

bash 复制代码
public class ThreadDemo {
	private static class MyRunnable implements Runnable {
		@Override
		public void run() {
		// 两种方法均可以
			while (!Thread.interrupted()) {
				//while (!Thread.currentThread().isInterrupted()) {
				System.out.println(Thread.currentThread().getName()
				+ ": 别管我,我忙着转账呢!");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				System.out.println(Thread.currentThread().getName()
				+ ": 有内鬼,终止交易!");
				// 注意此处的 break
				break;
				}
			}
			System.out.println(Thread.currentThread().getName()
	+ ": 啊!险些误了大事");
		}
	}
------------------------------------------------------------------
	public static void main(String[] args) throws InterruptedException 		{
		MyRunnable target = new MyRunnable();
		Thread thread = new Thread(target, "李四");
		System.out.println(Thread.currentThread().getName()
		+ ": 让李四开始转账。");
		thread.start();
		Thread.sleep(10 * 1000);
		System.out.println(Thread.currentThread().getName()
		+ ": 老板来电话了,得赶紧通知李四对方是个骗子!");
		thread.interrupt();
		}
}

thread 收到通知的方式有两种:

  1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以InterruptedException 异常的形式,清除中断标志。

当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法, 可以选择忽略这个异常, 也可以跳出循环结束线程

  1. 否则,只是内部的一个中断标志被设置,thread 可以通过

Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志

Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

bash 复制代码
/**
 * @author Zhang
 * @date 2024/5/416:27
 * @Description:
 */
public class Demo9 {

    public static void main(String[] args)  {
        Thread t = new Thread(() ->{
            //Thread类内部,有一个现成的标志位,可以判定当前的循环是否结束
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("线程工作中");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //throw new RuntimeException(e);
                    //1.假装没听见,循环继续正常执行
                    e.printStackTrace();
                    // 2.加上一个break,表示线程立即结束
                    //break;
                    //3.先做一些其他工作,完成之后再结束
                    //其他工作的代码
                    //break;
                }
            }
        });
        t.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("线程终止");
        t.interrupt();
    }
}

三、 等待一个线程join( )

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作

参考实例代码:

bash 复制代码
/**
 * @author Zhang
 * @date 2024/5/416:54
 * @Description:
 */
public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t =  new Thread(()->{
           for (int i = 0; i<5;i++ ){
               System.out.println("t 线程工作中");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();

        //让主线程等待t线程执行结束
        //一旦调用join,主线程就会出发阻塞。此时t线程就可以趁机完成后续的工作
        //一直阻塞到 t 执行完毕了, join才会解除阻塞,才能继续执行
        System.out.println("join 等待开始");
        t.join();
        //t.join 工作过程:
        //   1)如果t线程正在运行中,此时调用 join 的线程就会阻塞, 一直阻塞到t线程执行结束为止
        //   2)如果t线程已经执行结束了,此时调用 join 线程,就直接返回了,不会涉及到阻塞~~
        System.out.println("join 等待结束");
    }
}

其他一些 join( )方法

四、获取当前线程引用 和 休眠当前线程

4.1 获取当前线程引用

常见方法:public static Thread currentThread(); ------返回当前线程对象的引用

参考代码实例

bash 复制代码
public class ThreadDemo {
	public static void main(String[] args) {
		Thread thread = Thread.currentThread();
		System.out.println(thread.getName());
	}
}

4.2 休眠当前线程

bash 复制代码
public class ThreadDemo {
	public static void main(String[] args) throws InterruptedException {
		System.out.println(System.currentTimeMillis());
		Thread.sleep(3 * 1000);
		System.out.println(System.currentTimeMillis());
	}
}

五、 线程的状态


总结

好啦!以上就是今天要讲的内容,本文介绍了Thread类的start( )方法、线程的的中断、等待一个线程join( )、获取当前线程的引用,休眠当前线程,以及线程的引用。在本栏的下一节我们将会继续介绍Thread中重点内容------线程安全。

相关推荐
Renascence.40921 分钟前
力扣--649.Dota2参议院
java·数据结构·算法·leetcode
VaporGas29 分钟前
掌握Java封装:以猜拳小游戏为例,深入理解OOP
java·开发语言·学习·面向对象编程·oop·猜拳游戏·封装思想
小小工匠35 分钟前
加密与安全_ sm-crypto 国密算法sm2、sm3和sm4的Java库
java·算法·安全·sm2·sm3·sm4
程序员大金1 小时前
基于SpringBoot+Vue+MySQL的垃圾分类回收管理系统
java·vue.js·spring boot·后端·mysql·mybatis
陈小唬1 小时前
树形结构构建的两种方式
java·数据库·算法
CJH~1 小时前
Java入门:09.Java中三大特性(封装、继承、多态)01
java·开发语言·单例模式
打工人9961 小时前
反编译app
java
coding侠客1 小时前
Spring Boot 注解探秘:常用配置值读取注解的魔力
java·spring boot·后端·spring·spring cloud
暮志未晚Webgl1 小时前
94. UE5 GAS RPG 实现攻击击退效果
java·前端·ue5
程序员大金2 小时前
基于SpringBoot+Vue+MySQL的影院购票系统
java·vue.js·spring boot·后端·mysql·mybatis