线程停止以及中断

一. 启动线程的方式

1.run和start启动方式区别?

/**
 * create on 2020-12-23 13:17
 * run方式启动是由主线程来启动,start方式会新起一个线程来启动
 **/
public class CreateThreadAndStart {
    
    public static void main(String[] args) {
        Runnable runnable = ()->{
            System.out.println(Thread.currentThread().getName());
        };
        runnable.run();

        Thread t = new Thread(runnable);
        t.start();
    }

}

2.start()方法的含义

  • 启动新线程
  • 准备工作
  • 不能重复start()

3.start()源码解析

  • 启动新线程之前会先检查当前线程状态,只有NEW状态下的线程才会继续,否则会抛IllegalThreadStateException
  • 加入线程组中
  • 调用start0()(native方法,c++实现)方法
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

注意点:start方法是被synchronized修饰的方法,可以保证线程安全。由JVM创建的main方法线程和system组线程,并不会通过start方法启动。

4.run()方法源码解析

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

5.常见面试题

  • 一个线程两次调用start()方法会出现什么情况?为什么?
  • 既然start()方法会调用run()方法,为什么我们不直接去调用run()方法?

二.如何正确停止线程

原理介绍:使用 interrupt 来通知而不是强制停止

注意点:

在线程迭代过程中停车线程会以抛出interruptException异常作为中断信号
普通情况下需要配合Thread.currentThread.isInterrupt才能中断线程
如果while循环里面使用try/catch中断会失效(标记位会被清除)
如果不能抛出中断,就得传递中断,在字方法中try/catch中调用Thread.currentThread().interrupt()

响应中断的方法总结:

Object.wait()/wait(long)/wait(long,int)
Thread.sleep(long)/sleep(long,int)
Thread.join()/join(long)/join(long,int)
java.util.concurrent.BlockingQueue.take()/put(E)
java.util.concurrent.locks.Lock.lockInterruptibly()
java.util.concurrent.CountDownLatch.await()
java.util.concurrent.CyclicBarrier.await()
java.util.concurrent.Exchanger.exchange(V)
java.nio.channels.InterruptibleChannel相关方法
java.nio.channels.Selector的相关方法

三.Java异常体系

                                        StackOverflowError
                    VirtualMachineError ...
                    ...                 OutOfMemoryError
            Error
                    AWTError
                              
 Throwable                               AirthmeticException
                                         ...
                    RuntimeException     NullPointerException
                                         IndexOutOfBoundsException
            Exception ...            
                                EOFException
                    IOException ...
                                FileNotFoundException

四.常见面试题

如何停止线程?

A.用volatile的boolean作为标记来停止
B.用stop()方法来让线程停止
C.用interrupt来请求线程停止
解答:C
1.原理:用interrupt来请求线程停止,不是强制
2.想停止线程,要求请求发、被停止方、字方法被调用方互相配合才可以:

a)作为请求方:每次循环中或者适时检查中断信号,并且在可能抛出InterruptedException的地方处理中断信号
b)请求方:发出中断信号
c)字方法调用方(被线程调用的方法的作者)要注意:优先在方法层面抛出InterruptedException,或者检查到中断信号时,再次设置中断状态(传递中断信号)

3.最后再说错误的方法:stop/suspend已废弃,volatile的boolean无法处理长时间堵塞的情况

无法响应中断时如何停止线程?

A.用interrupt方法来请求停止
B.不可中断的阻塞无法处理
C.根据不同的类调用不同的方法

解答:C
如果线程阻塞是由于调用了wait(),sleep()或join()方法,你可以中断线程,通过抛出interruptedException异常来唤醒该线程

但是对于不能响应InterruptedException的阻塞,很遗憾并没有一个通用的解决方法
但是我们可以利用特定的其他的可以响应中断的方法,比如ReentrantLock.lockInterruptibly(),比如关闭嵌套字使线程立即返回等方法来达到目的。
答案有很多种,因为很多原因会造成线程阻塞,所以针对不同情况唤起的方法也不同
总结就是如果不支持响应中断,就要用特定的方法来唤醒,没有万能药。

以上文章内容整理自慕课网悟空老师视频内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值