线程的启动与安全中止

一、线程的启动

线程有两种启动方式,即继承Thread类与重写Runable接口,如下:
在这里插入图片描述


1.1、Thread

有关 Thread 创建线程,在初识Java多线程中的线程的创建函数其实已经介绍过了,这里就不赘述了。


1.2、Runnable

Runnable 和 Thread 这二者本身其实就没有本质区别,就是接口和类的区别,重写 Runnbale 还是需要通过 Thread 来启动线程。


在使用中,由于Java不允许多继承,Runnable 可以避免单继承局限所带来的困扰。


1.3、Callable

由于 Runnable 接口是没有返回值的,有的场景下需要返回值的话,这时就需要使用到 Callable 接口了。

public class App {
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}

class MyCallable implements Callable<String> {
    
    
    @Override
    public String call() throws Exception {
    
    
        return "success";
    }
}

其中借助了 FutureTask 类来执行,FutureTask 类同时实现了 Future 和 Runnable 接口,所以它既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。
在这里插入图片描述

其中需要注意的就是,在获取返回值时,使用的 FutureTask.get() 是一个阻塞方法,一旦调用了该方法,后续代码就阻塞,只能等待的 Callable 的方法执行完成,才会继续执行。


二、线程的中止

通常可能会有这样的需求,即停止一个线程。在Java的api中存在 suspend()resume()stop() 等方法,其作用分别是挂起线程、恢复线程的执行、终止线程。
在这里插入图片描述

但是发现这三个方法,已经不推荐使用了,因为三个方法对我们的线程进行立即操作,如 stop()suspend() 方法会立即将我们的线程停止、挂起,但是对线程中的资源不会进行释放,可能会造成程序的死锁问题。


2.1、interrupt() 与 isInterrupted() 方法

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以可以使用 interrupt() 方法来通知线程应该中断了,但是具体是否中断还是继续运行,应该由被通知的线程自己处理。


调用 interrupt() 方法只会将线程的中断标志置于 true,而不是强制中断。同时Java中还提供了查询线程是否中断的标志的方法 isInterrupted() 以及静态方法 Thread.interrupted(),区别在于静态方法在查询完我们线程中断状态后会将状态置于 false。
在这里插入图片描述

在下列测试中就可以发现,查询线程是否中断的标志的静态方法 Thread.interrupted() 就将中断标志修改为了false,另外这里是直接使用main线程来查看的,如果是创建了新的线程进行测试,则需先将线程启动,并保持运行状态,不然查询肯定都是false
在这里插入图片描述


另外不建议自定义一个取消标志位来中止线程的运行。因为 run() 方法里有阻塞时,就会无法检测到自定义取消标志,线程必须从阻塞调用返回后,才会检查这个取消标志。


2.2、InterruptedException 异常

如果一个线程处于了阻塞状态时(如线程调用了 thread.sleep()、thread.join()、 thread.wait() 等),这时调用 interrupt 方法进行中断操作,则会抛出 InterruptedException 异常,但是在抛出异常后会立即将线程的中断标示位清除,即重新设置为 false。
在这里插入图片描述


所以我们在 InterruptedException异常的中,如果确认是需要中断线程的,这里我们一定要再次设置我们的中断标志。
在这里插入图片描述


2.3、FutureTask

实现了 Future 接口的 FutureTask 还为我们提供了其他的中断方法,如 cancel() 也是可以发出一个中断信号的。


另外FutureTask 类还提供了 isDone()isCancelled(),分别用来判断任务是否完成,任务是否被取消。
在这里插入图片描述

  • cancel(boolean): 任务被取消返回true,否则false
    1. cancel(true):会中断正在运行的任务
    2. cancel(false):不会中断已经在运行的任务
  • isDone(): 任务是否完成,无论是正常结束,还是异常结束,或者自己取消,都返回 true
  • isCancelled(): 任务是否在完成前被取消

猜你喜欢

转载自blog.csdn.net/rockvine/article/details/124972509
今日推荐