文章目录
一、线程的启动
线程有两种启动方式,即继承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
- cancel(true):会中断正在运行的任务
- cancel(false):不会中断已经在运行的任务
- isDone(): 任务是否完成,无论是正常结束,还是异常结束,或者自己取消,都返回 true
- isCancelled(): 任务是否在完成前被取消