一、暂停、恢复和停止操作对应在线程Thread的API是suspend()、resume()和stop()。
但是这些API不建议使用,因为这些方法会带来副作用。比如:suspend()方法在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入挂起状态,这样容易引发死锁。同样,stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态。
推荐配合使用Object的wait()、notify()、notifyAll()来控制线程的执行。
二、终止一个线程
1.安全的中止一个线程是其他线程通过调用某个线程A的interrupt()方法对其进行中断操作。
中断好比其他线程对该线程打了个招呼,"线程A,你要中断了",不代表线程A会立即停止自己的工作,同样的线程A完全可以不理会这种中断请求。Java里的线程默认是抢占式的,可以调用yield或join等方法变成协作式的调度。
2.线程通过检查自身的中断标志位是否被置为true来进行响应,线程通过方法isInterrupted()来进行判断是否被中断,也可以调用静态方法Thread.interrupted()来进行判断当前线程是否被中断,不过静态方法Thread.interrupted()会同时将中断标识位改写为false。
3.如果一个线程处于了阻塞状态(如线程调用了Thread.sleep、Thread.join),则线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后会立即将线程的中断标示位清除,即重新设置为false。
4.不建议自定义一个取消标志位来中止线程的运行。因为run方法里有阻塞调用时会无法很快检测到取消标志,线程必须从阻塞调用返回后,才会检查这个取消标志。这种情况下,使用中断会更好,因为:
1)一般的阻塞方法,如sleep等本身就支持中断的检查。
2)检查中断位的状态和检查取消标志位没什么区别,用中断位的状态还可以避免声明取消标志位,减少资源的消耗。
5.处于死锁状态的线程无法被中断。
三、start()方法让一个线程进入就绪队列等待分配CPU,分到CPU后才调用实现的run()方法,而且start()方法不能重复调用。
四、yield()方法:使当前线程让出CPU占有权,但让出的时间是不可设定的。也不会释放锁资源,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行。
五、join方法:将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的join()方法,则直到线程A执行完毕后,才会继续执行线程B。
六、其他
1.不要依赖线程优先级,因为操作系统可能会忽略它。
2.避免在构造函数或finalize()方法中启动线程。构造函数中对象可能还未完全构造好。finalize()的调用时机不确定。
3.频繁创建销毁线程开销大,应该使用线程池,例如:ExecutorService。
4.不应在多个线程共享一个SimpleDateFormat实例,因为它不是线程安全的。
5.守护线程在JVM退出时不会阻止JVM的关闭,故不能在守护线程运行长时间执行的任务。
微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。
我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。
欢迎关注。助您在编程路上越走越好!