多线程-04-线程的常用方法

发布于:2024-11-28 ⋅ 阅读:(10) ⋅ 点赞:(0)

Thread类常见方法

方法名 功能说明 注意事项
start() 启动一个新线程,在新的线程运行 run 方法中的代码 start 方法只是让线程进入就绪,里面代码不一定立刻运行(CPU 的时间片还没分给它)。每个线程对象的start方法只能调用一次,如果调用了多次会出现IllegalThreadStateException (start方法才是启动线程的方法,直接调用run方法是没有用的
run() 新线程启动后会调用的方法 如果在构造 Thread 对象时传递了 Runnable 参数,则线程启动后会调用 Runnable 中的 run 方法,否则默认不执行任何操作(因为默认Thread类的run方法里面是没有任何代码的),但可以创建 Thread 的子类对象,来覆盖默认行为
join() 等待线程运行结束 在一个线程的代码里面调用另一个线程的join方法时,当前线程会阻塞(即暂停执行),直到被join的线程完成其执行。(join方法会抛出InterruptedException异常,这表明当前线程在等待过程中被中断。因此,调用join方法时通常需要使用try-catch块来处理这个异常。)
join(long n) 等待线程运行结束,最多等待 n 毫秒 在一个线程的代码里面调用另一个线程的join方法时,当前线程会阻塞(即暂停执行),阻塞n毫秒,如果n毫秒内线程完成执行了,那么就阻塞到被join的线程执行完成
getId() 获取线程长整型的 id id 唯一
getName() 获取线程名
setName(String) 修改线程名
getPriority() 获取线程优先级
setPriority(int) 修改线程优先级 java中规定线程优先级是1~10 的整数,较大的优先级能提高该线程被 CPU 调度的机率
getState() 获取线程状态 Java 中线程状态是用 6 个 enum 表示,分别为:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
isInterrupted() 用于检查线程的中断状态 当一个正在运行的线程被中断时,它的中断状态会被设置为true。线程可以通过调用自身的interrupt()方法来请求中断,而其它线程则可以通过调用这个线程的interrupt()方法来中断它。(调用isInterrupted()方法不会清除打断标记)
interrupt() 打断线程 如果被打断的线程正在 sleep,wait,join 会导致被打断的线程抛出 InterruptedException,并清除打断标记 ;如果打断的线程是正在运行的线程,则会设置打断标记 ;正在park 的线程被打断,也会设置 打断标记
interrupted() static 方法,判断当前线程是否被打断 会清除打断标记
isAlive() 线程是否存活(还没有运行完毕) 1、如果线程已经通过调用 start() 方法启动,并且尚未通过调用 run() 方法的结束或异常终止,那么 isAlive() 将返回 true;2、即使线程在执行过程中被中断(通过调用 interrupt() 方法),只要 run() 方法尚未完成,isAlive() 仍然会返回 true
currentThread() static方法 ,获取当前正在执行的线程
sleep(long n) static方法,让当前执行的线程休眠n毫秒,休眠时让出 cpu 的时间片给其它线程 1. 调用 sleep 会让 当前线程从 Running 进入 Timed Waiting 状态(阻塞) 2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException3. 睡眠结束后的线程未必会立刻得到执行4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
yield() static方法,提示线程调度器让出当前线程对CPU的使用 (此方法主要是为了测试和调试)1. 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程 2. 具体的实现依赖于操作系统的任务调度器
void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出(这个方法必须在start方法之前调用 1、垃圾回收器线程就是一种守护线程。2、Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等待它们处理完当前请求

park线程(认识)

  1. Park线程的定义

    • 在Java中,当线程无法继续执行时,它会被暂时挂起,等待某种条件的到来再继续执行,这种状态被称为线程的Parking状态。LockSupport类提供了park()unpark(Thread thread)这两个核心方法,用于实现线程的阻塞和解除阻塞
  2. Park线程的方法

    • park()方法
      • 作用:使当前线程进入等待状态(阻塞),直到被唤醒或者中断。
      • 调用方式:可以直接调用LockSupport.park()方法,使当前线程阻塞。
    • unpark(Thread thread)方法
      • 作用:解除指定线程的阻塞状态,使其可以继续执行。
      • 调用方式:通过调用LockSupport.unpark(Thread thread)方法,并传入需要解除阻塞的线程对象作为参数。
  3. Park线程的工作机制

    • 线程阻塞:当线程调用park()方法时,它会检查自己的状态。如果状态允许线程继续执行,则线程会继续执行;否则,线程会被放入休眠状态,等待被唤醒。
    • 线程唤醒:当其他线程调用unpark(Thread thread)方法,并传入需要唤醒的线程对象时,该线程会从休眠状态被唤醒,并检查自身状态。如果满足条件,则线程会立即恢复执行。
  • 注意:
    • 如果要执行打断的线程标记是true,LockSupport.park()方法失效。因为打断线程的标记为true,则说明当前线程已经处于阻塞了,所以无法执行LockSupport.park()方法。因此用Thread.currentThread().interrupted()判断当前线程标记,此方法最后会把标记刷回false
    • park中断是WAITTING状态,可以通过线程的getState()方法查看。

终止模式之两阶段终止(两个阶段:准备阶段和终止阶段)

模式介绍:在一个线程 T1 中“优雅”地终止线程 T2。(这里的【优雅】指的是给 T2 一个料理后事的机会)

1. 错误思路

  1. 使用线程对象的 stop() 方法停止线程
    • stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其它线程将永远无法获取锁
    • 使用 System.exit(int) 方法停止线程
      • 我们的目的仅是停止一个线程,但这种做法会让整个程序都停止

2. 正确思路

在这里插入图片描述

  • 利用 isInterrupted方法:调用isInterrupted()方法不会清除打断标记

    • interrupt 可以打断正在执行的线程,无论这个线程是在 sleep,wait,还是正常运行。如果被打断的线程正在 sleep,wait,join 会导致被打断的线程抛出 InterruptedException,并清除打断标记如果打断的线程是正在运行的线程,则会设置打断标记 ;正在park 的线程被打断,也会设置 打断标记
  • 线程类:

public class TPTInterrupt {
	 private Thread thread;
	 public void start(){
		 thread = new Thread(() -> {
			 while(true) {
				 Thread current = Thread.currentThread();
				 if(current.isInterrupted()) {  // 如果当前线程被打断了
					 log.debug("料理后事");
					 break;// 跳出循环
				 }
				 try {
					 Thread.sleep(1000);
					 log.debug("将结果保存");
				 } catch (InterruptedException e) {
				 	current.interrupt();// 重新设置打断标记
				 }
				 // 执行监控操作 
			}
		},"监控线程");
		thread.start();
	 }
	 
	 public void stop() {
		 thread.interrupt();
	 }
}
  • 调用线程方法:

public class test {
    public static void main(String[] args) {	
		TPTInterrupt t = new TPTInterrupt();
		t.start();
		Thread.sleep(3500);
		log.debug("stop");
		t.stop();
	}
}

模式使用场景:后台监控线程

  1. 场景描述:
    • 有一个后台监控线程,每隔一段时间返回一次监控结果。
    • 当需要停止监控时,需要确保线程能够优雅地终止,释放资源。
  2. 实现步骤:
    • 准备阶段:设置一个中断标志或调用线程的interrupt()方法,通知线程准备停止运行。
    • 终止阶段:线程在检测到中断标志或捕获到InterruptedException异常后,执行必要的清理工作(如释放资源、关闭连接等),然后真正终止线程。