对线面试官-线程入门第一课

2023-09-08 17:14:54 浏览数 (1)

面试官:能聊一聊线程吗?什么是线程?它和进程有什么区别吗?

派大星:假设一个程序例如:weChat.exe这是一个程序,一个静态的概念,双击运行。而进程是相对于程序来说是一个动态的概念。作为进程里面最小的执行单元便是线程。通俗的讲一个程序里不同的执行路径就是线程

面试官:run方法和start方法有什么区别?

派大星:run()方法是一个方法调用。start()方法是Thread类里的一个方法。start()方法会产生一个分支和主方法一同执行。

面试官:线程的几种状态可以简单说一说吗?

派大星:好的

  • New(新创建)
  • Runnable(可运行)里面有ready和running两个状态
  • Blocked(被阻塞)未获得锁的时候
  • Waiting(等待)调用join()wait()part()方法
  • Timed Waiting(计时等待)时间结束的时候。比如:sleep(1000)
  • Terminated(被终止)

面试官:创建线程的几种方式?有了解吗?可以详细聊一聊吗?

派大星:好的。主要有以下几种方式:

  1. 继承Thread类,重写run方法。
  2. 实现Runnable接口,重写run方法。

当然,还有类似的变种方法:JDK8的lambda表达式的写法。当然还可以通过线程池来启动Executors.newCachedThread当然这种底层也是采用上述两种方式实现的。

面试官:了解线程里的sleep()yield()join()``interrupt方法吗?

派大星:sleep()方法会让出CPU让其它线程执行,yield()会让线程重新回到等待队列中让出CPU但是也有可能下次执行的还是当前线程,也就是让线程回到就绪状态join()方法:假设t1线程执行到中途调用了t2.join()这是t1需要等待t2执行完成之后才会继续执行下去,经常用来等待另外一个线程的结束。

这里就引出了一个经典的线程题:如何保证线程t1、t2、t3依次顺序执行完成。很简单:只需要在主线程中填加t1.join() t2.join() t3.join() 。或者在t1线程中填加t2.join(),在t2线程中填加t3.join()即可实现。

interrupt方法线程调用interrupt方法打断线程,然后通过方法interrupted方法,可以获取到打断信号。通过这个信号,可以在代码逻辑中停止线程。通过开关的方式打断异常时,需要定义一个volatile标识的变量,通过判断这个变量来打断线程

面试官:sleep、yield、wait、notify、notifyAll是否释放锁?

派大星:

  • sleep 和 yield 方法都是不会释放锁的

调用 sleep() 方法使线程进入等待状态,等待休眠时间达到,而调用我们的 yield() 方法,线程会进入就绪状态,也就是sleep()需要等待设置的时间后才会进行就绪状态,而yield会立即进入就绪状态

  • wait、notify和notifyAll都会释放锁

wait 方法执行后会立即释放锁,等待被唤醒的时候会重新持有锁 notify和notifyAll也会释放锁,但是不是立即释放锁,执行完notify/notifyAll方法后会立即通知其它正在等待的线程,但不是立即释放锁,而是会等到其synchronized内中的代码全部执行完之后,才会释放锁。所以我们一般都是在我们synchronized内的最后才会调用 notify/notifyAll

面试官:wait 与 notify 为什么是 Object 的成员方法?

派大星:

  • 我们都知道,synchronized 关键字可以加在任何对象的成员函数上,任何对象也都可以成为锁。那么,wait() 和 notify() 这样普及,Object 又是所有类的基类,那么 wait() 和 notify() 放在Object 里面最合适不过。wait和nofity不是常见的普通java方法或同步工具,在Java中它们更多的是实现两个线程之间的通信机制。如果不能通过类似synchronized这样的Java关键字来实现这种机制,那么Object类中就是定义它们最好的地方,以此来使任何Java对象都可以拥有实现线程通信机制的能力。
  • 记住synchronized和wait,notify是两个不同的问题域,并且不要混淆它们的相似或相关性。同步类似竞态条件,是提供线程间互斥和确保Java类的线程安全性的,而wait和notify是两个线程之间的通信机制。
  • 另一个原因:每个对象都可以作为锁

在Java中,为了进入临界区代码段,线程需要获得锁并且它们等待锁可用,它们不知道哪些线程持有锁而它们只知道锁是由某个线程保持,它们应该等待锁而不是知道哪个线程在同步块内并要求它们释放锁。这个比喻适合等待和通知在object类而不是Java中的线程。

0 人点赞