线程、多线程与线程池面试题

2022-08-24 09:07:49 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

● 概念

线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程。

多线程:解决多任务同时执行的需求,合理使用CPU资源。多线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多 线程运行具有不确定性。

线程池:基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

● 线程

创建线程的两种方式:

一、继承Thread类,扩展线程。

代码语言:javascript复制
class DemoThread extends Thread { @Override public void run() { super.run(); // Perform time-consuming operation... } } DemoThread t = new DemoThread(); t.start(); 
  • 继承Thread类,覆盖run()方法。
  • 创建线程对象并用start()方法启动线程。

面试题

  • 1)线程和进程有什么区别?

一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

  • 2)如何在Java中实现线程?

创建线程有两种方式: 一、继承 Thread 类,扩展线程。 二、实现 Runnable 接口。

  • 3)Thread 类中的 start() 和 run() 方法有什么区别?

调用 start() 方法才会启动新线程;如果直接调用 Thread 的 run() 方法,它的行为就会和普通的方法一样;为了在新的线程中执行我们的代码,必须使用 Thread.start() 方法。

二、实现Runnable接口。

  • 1)用 Runnable 还是 Thread ?

我们都知道可以通过继承 Thread 类或者调用 Runnable 接口来实现线程,问题是,创建线程哪种方式更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用Runnable接口更好了。

● 线程的状态以及状态之间的相互转换

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

  • wait和sleep的区别:

线程访问:

锁池状态,之后等待锁释放,然后访问代码

wait

等待队列(释放资源)—>调用notify或者notifyall之后锁池状态—>( 等待锁释放)—>可运行状态—>运行状态—->访 问代码

sleep,join

不释放资源–>结束后直接进入可运行状态—>运行状态—->访问代码

一个java控制台程序,默认运行两个线程,一个主线程,一个垃圾回收线程。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/139890.html原文链接:https://javaforall.cn

0 人点赞