Java岗面试题--Java并发(日积月累,每日三题)

目录

  • 面试题一:为什么调用 start() 方法时会执行 run() 方法,那怎么不直接调用 run() 方法?(线程的 run() 和 start() 有什么区别? )
  • 面试题二:线程状态及转换?
  • 面试题三:线程有哪些常用的调度方法?
        • 线程等待的方法:
        • 唤醒线程方法:
        • 线程休眠
        • 让出优先权
        • 线程中断

面试题一:为什么调用 start() 方法时会执行 run() 方法,那怎么不直接调用 run() 方法?(线程的 run() 和 start() 有什么区别? )

每个线程都是通过某个特定 Thread 对象所对应的方法 run() 来完成其操作的,run() 方法称为线程体。通过调用 Thread 类的 start() 方法来启动⼀个线程;

  1. start() 方法来启动⼀个线程,真正实现了多线程运行。这时无需等待 run() 方法体代码执行完毕,可以直接继续执行下面的代码;这时此线程是处于就绪状态,并没有运行。然后通过此 Thread 类调用方法 run() 来完成其运行状态,这里方法 run() 称为线程体,它包含了要执行的这个线程的内容,run() 方法运行结束,此线程终止。然后 cpu 再调度其它线程;
  2. run() 方法是在本线程里的,只是线程里的⼀个函数,而不是多线程的。如果直接调用 run(),其实就相当于是调用了⼀个普通函数而已,直接调用 run() 方法必须等待 run() 方法执行完毕才能执行下面的代码,所以执行路径还是只有⼀条,根本就没有线程的特征,所以在多线程执行时要使用 start() 方法法而不是 run() 方法。

JVM 执行 start 方法,会先创建一条线程,由创建出来的新线程去执行 Thread 的 run() 方法,这才起到多线程的效果。如果直接调用 Thread 的 run()方法,那么run方法还是运行在主线程中,相当于顺序执行,就起不到多线程的效果。

面试题二:线程状态及转换?

Thread 的源码中定义了6种状态:

  1. new(新建)
  2. runnnable(可运行)
  3. blocked(阻塞)
  4. waiting(等待)
  5. time waiting (定时等待)
  6. terminated(终止)
    Java岗面试题--Java并发(日积月累,每日三题)_第1张图片
    Java岗面试题--Java并发(日积月累,每日三题)_第2张图片

面试题三:线程有哪些常用的调度方法?

在 Object 类中有一些函数可以用于线程的等待与通知。

线程等待的方法:

wait():当一个线程 A 调用一个共享变量的 wait()方法时, 线程 A 会被阻塞挂起, 发生下面几种情况才会返回 :

  1. 线程 A 调用了共享对象 notify() 或者 notifyAll() 方法;
  2. 其他线程调用了线程 A 的 interrupt() 方法,线程 A 抛出 InterruptedException 异常返回。

wait(long timeout) :这个方法相比 wait() 方法多了一个超时参数,它的不同之处在于,如果线程 A 调用共享对象的 wait(long timeout) 方法后,没有在指定的 timeout ms时间内被其它线程唤醒,那么这个方法还是会因为超时而返回。

wait(long timeout, int nanos),其内部调用的是 wait(long timout)函数。

唤醒线程方法:

notify() : 一个线程 A 调用共享对象的 notify() 方法后,会唤醒一个在这个共享变量上调用 wait 系列方法后被挂起的线程。一个共享变量上可能会有多个线程在等待,具体唤醒哪个等待的线程是随机的。

notifyAll() :不同于在共享变量上调用 notify() 函数会唤醒被阻塞到该共享变量上的一个线程,notifyAll() 方法则会唤醒所有在该共享变量上由于调用 wait 系列方法而被挂起的线程。

Thread 类也提供了一个方法用于等待的方法 join():如果一个线程 A 执行了 thread.join() 语句,其含义是:当前线程 A 等待 thread 线程终止之后才从 thread.join() 返回。

线程休眠

sleep(long millis) : Thread 类中的静态方法,当一个执行中的线程 A 调用了 Thread 的 sleep 方法后,线程 A 会暂时让出指定时间的执行权,但是线程 A 所拥有的监视器资源,比如锁还是持有不让出的。指定的睡眠时间到了后该函数会正常返回,接着参与 CPU 的调度,获取到 CPU 资源后就可以继续运行。

让出优先权

yield() :Thread 类中的静态方法,当一个线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己的 CPU 。

线程中断

Java 中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被中断的线程根据中断状态自行处理。

void interrupt() :中断线程,例如,当线程 A 运行时,线程 B 可以调用线程 interrupt() 方法来设置线程的中断标志为true 并立即返回。设置标志仅仅是设置标志,线程 A 实际并没有被中断, 会继续往下执行。

boolean isInterrupted() 方法:检测当前线程是否被中断。

boolean interrupted() 方法:检测当前线程是否被中断,与 isInterrupted 不同的是,该方法如果发现当前线程被中断,则会清除中断标志。

你可能感兴趣的:(Java,面试题,java,面试)