一、背景

这篇博客想要讲解的是线程的暂停与停止。暂停与停止的方法各有其特点与优缺点,我会在这里逐一进行分析,并且大都是用举例子的方式来进行阐述。

二、线程的暂停

suspend和resume

线程的暂停使用的是suspend和resume方法,我写了程序进行验证。

windows java进程停掉怎么办 java进程暂停_java


windows java进程停掉怎么办 java进程暂停_停止线程_02

这段代码运行出来的结果如下:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_03


可见suspend和resume的功能:suspend可以使一个线程暂时停止运行,resume可以恢复被暂停的线程。

suspend和resume“独占”的缺点

就是说,如果被挂起的线程正在访问临界资源,那么这个时候其它线程也无法对该临界资源进行访问,也就使“独占”一词的来源。

下面举一个有趣的例子:

先来看这段程序:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_04


windows java进程停掉怎么办 java进程暂停_停止线程_05


这段程序十分简单,很明显,最后输出的结果应该使MAIN END!!!!!

没错,输出结果如下:

windows java进程停掉怎么办 java进程暂停_java_06


那么,我们再来看这段程序:

windows java进程停掉怎么办 java进程暂停_停止线程_07


windows java进程停掉怎么办 java进程暂停_多线程_08


可以发现,这段程序与上一段程序唯一的不同在于我再MyThread类run方法中添加了一个将i值打印出来的语句。按道理讲,这段代码的输出应该是将i的值不断的输出,知道该线程被挂起,然后输出MAIN END!!!!!

但是事实上,输出结果的结果并没有MAIN END!!!!!

结果如下:

windows java进程停掉怎么办 java进程暂停_java_09


这是为什么呢?

我们来看一下println的源码:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_10


这下你或许明白了,因为由关键字synchronized,所以这段代码是临界区,在MyThread线程在对其进行访问的时候被暂停了,那么,其它线程当然也无法访问这段代码,所以main中的println迟迟无法打印出结果来。这就是suspend与resume的“独占”缺点。

三、线程的停止

interrupt、interrupted、isInterrupted

interrupt

要介绍这三种方法,先来看一段代码:

windows java进程停掉怎么办 java进程暂停_线程_11


windows java进程停掉怎么办 java进程暂停_java_12


这段代码的运行结果如下:

windows java进程停掉怎么办 java进程暂停_停止线程_13


也就是说,从1一直输出到500000,而interrupt方法好像没有起什么作用,

事实上并不是的,interrupt方法只是给该线程发出了一个停止的信号,至于怎么使用这个信号,就要看interrupted和isInterrupted了。因为interrupted和isInterrupted可以用来判断一个线程是否有处于停止状态,判断出来停止状态就可以使用if语句来进行适当的操作。

interrupted

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_14


windows java进程停掉怎么办 java进程暂停_java_15


运行结果如下:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_16


为什么测试出来的是否由停止信号还是false呢?

原因在于interrupted测试的是当前线程,也就是这段程序中的main线程是否停止,当然main线程没有停止,所以interrupted返回的是false。

那么我再将源程序改一下,将main也用interrupt来停止一下:

程序如下:

windows java进程停掉怎么办 java进程暂停_线程_17


windows java进程停掉怎么办 java进程暂停_停止线程_18


这时的运行结果如下:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_19


如结果所示,返回的第一个值是true,也就是说检测到了main有停止信号,但是为什么第二个值又是false呢?

原因在于interrupted这个方法在输出true之后会将停止状态清除掉,那么第一个方法将停止状态清除掉了,自然而然第二个interrupted返回的是false。

isInterrupted

接下来我们来看一下isInterrupted方法。

isInterrupted的方法返回值不同于interrupted。其可以判断其它线程的停止状态,而且它不会清除停止状态。

示例程序如下:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_20


windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_21


运行结果如下:

windows java进程停掉怎么办 java进程暂停_多线程_22

break,return,throw new InterruptedException()

break、return和throw new InterruptedException()可以与interrupted或isInterrupted的if语句搭配来使用

我这里只演示一下break的用法,return、throw new InterruptedException()类似

windows java进程停掉怎么办 java进程暂停_java_23


windows java进程停掉怎么办 java进程暂停_线程_24


运行结果如下:

windows java进程停掉怎么办 java进程暂停_停止线程_25


这里需要注意的是,虽然break和return、throw new InterruptedException()的用法类似,但是实际上break只是跳出了循环而已,并没有真正的结束线程,而return、throw new InterruptedException()可以真正的结束线程,另外throw new InterruptedException()会将程序跳转至run方法中的catch。这样可以对异常信息进行相关处理,而且不至于使程序中出现很多break和return造成污染。

沉睡中停止线程

如果在沉睡中停止线程会出现什么情况呢?

看如下程序:

windows java进程停掉怎么办 java进程暂停_java_26


windows java进程停掉怎么办 java进程暂停_停止线程_27


结果如下:

windows java进程停掉怎么办 java进程暂停_windows java进程停掉怎么办_28


看到这个结果我们可以得出来两个信息:

1.线程在沉睡中如果被停止就会直接进入catch中

2.进入catch语句之前会清除停止状态值那么,如果是先停止线程,然后线程要进入睡眠会出现什么情况呢?

示例程序如下:

windows java进程停掉怎么办 java进程暂停_线程_29


windows java进程停掉怎么办 java进程暂停_多线程_30


结果如下:

windows java进程停掉怎么办 java进程暂停_多线程_31


可以看到,与上面类似,仍旧是进入catch,并且会清除停止状态值。

stop

stop这个方法十分暴力,用的时候需谨慎。

我这里写了一个示例程序如下:

windows java进程停掉怎么办 java进程暂停_java_32


windows java进程停掉怎么办 java进程暂停_停止线程_33


输出结果如下:

windows java进程停掉怎么办 java进程暂停_线程_34


可以看到,正在运行着的线程直接就被停止掉,stop方法看起来十分简单易用,实际上则会出现一些问题。比如stop会释放锁,这会造成数据不同步的不良后果。而且stop会让线程停止,则有可能一些清理工作得不到完成.

四、总结

这篇博客主要讲解了Java多线程中一些在暂停与停止线程中常用的方法还有它们的用途以及优缺点。其中,stop、suspend、resume在使用时需慎重,因为它们有可能会引起某些麻烦。