Java多线程面试问题及解决办法(一)-乐题库

***:Java多线程面试题

1:进程和线程有什么区别?

进程是一个自包含的运行时环境,可以看作是程序或应用程序。线程是在进程中执行的任务。Java 运行时环境是一个包含不同类和程序的单一进程。线程可以称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以在进程内共享资源。

2:多线程编程有什么好处?

在多线程程序中,多个线程并发执行以提高程序的效率,CPU不会因为线程需要等待资源而进入空闲状态。多个线程共享堆内存,因此创建多个线程来执行某些任务比创建多个进程要好。例如,Servlet 比 CGI 更好,因为 Servlet 支持多线程,而 CGI 不支持。

3:用户线程和守护线程有什么区别?

当我们在 Java 程序中创建线程时,它被称为用户线程。守护线程是在后台执行并且不会阻止 JVM 终止的线程。当没有用户线程在运行时,JVM 关闭程序并退出。由守护线程创建的子线程仍然是守护线程。

4:我们如何创建线程?

创建线程有两种方式:一种是实现Runnable接口,然后将其传递给Thread构造函数来创建Thread对象;另一种是直接继承Thread类。

5:有哪些不同的线程生命周期?

当我们在 Java 程序中创建一个新线程时,它的状态是 New。当我们调用线程的 start() 方法时,状态变为 Runnable。线程调度程序将 CPU 时间分配给 Runnable 线程池中的线程,并将它们的状态更改为 Running。其他线程状态是 Waiting、Blocked 和 Dead。

6:可以直接调用Thread类的run()方法吗?

当然,但是如果我们调用 Thread 的 run() 方法,它将表现得像一个普通的方法。要在新线程中执行我们的代码,我们必须使用 Thread.start() 方法。

7:如何暂停一个正在运行的线程一段时间?

我们可以使用Thread类的Sleep()方法让线程暂停一段时间。注意,这并不会终止线程,一旦线程从睡眠中被唤醒,线程的状态将变为Runnable,并根据线程调度执行。

8:你对线程优先级的理解是什么?

每个线程都有一个优先级。一般来说,高优先级的线程在运行时会有优先级,但这取决于线程调度的实现,这取决于操作系统。我们可以定义线程的优先级,但这并不能保证较高优先级的线程将在较低优先级的线程之前执行。线程优先级是一个int变量(从1-10),1表示***优先级,10表示***优先级。

9:什么是线程调度器和时间片?

线程调度器是一个操作系统服务,负责为处于可运行状态的线程分配 CPU 时间。一旦我们创建了一个线程并启动它,它的执行就依赖于线程调度器的实现。时间片是指将可用 CPU 时间分配给可用 Runnable 线程的过程。分配 CPU 时间可以基于线程优先级或线程等待的时间。线程调度不受Java虚拟机控制,所以最好让应用程序来控制它(即不要让你的程序依赖于线程优先级)。

10:在多线程中,什么是上下文切换?

上下文切换是存储和恢复 CPU 状态的过程,它使线程执行能够从中断点恢复执行。上下文切换是多任务操作系统和多线程环境的基本特征。

11:为什么Thread类的sleep()和yield()方法是静态的?

Thread 类的 sleep() 和 yield() 方法将在当前正在执行的线程上运行。所以在其他等待的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前执行的线程中工作,避免程序员错误地认为这些方法可以从其他未运行的线程中调用。

12:如何保证线程安全?

在 Java 中有很多方法可以确保线程安全——同步、使用原子并发类、实现并发锁、使用 volatile 关键字、使用不可变和线程安全类。您可以在线程安全教程中了解更多信息。

13:如何创建守护线程?

使用 Thread 类的 setDaemon(true) 方法将线程设置为守护线程。需要注意的是,这个方法需要在调用start()方法之前调用,否则会抛出IllegalThreadStateException。

14:什么是ThreadLocal?

ThreadLocal用于创建线程局部变量,我们知道一个对象的所有线程都会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步时,我们可以选择 ThreadLocal 变量。每个线程都有自己的 Thread 变量能让线程停止执行的有,它们可以使用 get() set() 方法来获取它们的默认值或在线程内更改它们的值。ThreadLocal 实例通常被认为是与线程状态相关的私有静态属性。

二:Java并发面试题

1:什么是Executors框架?

Executor 框架是在 Java 5 中引入的,带有 java.util.concurrent.Executor 接口。Executor框架是一个异步任务的框架,根据一组执行策略被调用、调度、执行和控制。以错误的方式创建线程会导致应用程序内存溢出。所以创建线程池是一个更好的解决方案,因为你可以限制线程的数量并回收它们。使用 Executors 框架可以非常方便地创建线程池。

2:什么是Callable和Future?

Java 5 在并发包中引入了 java.util.concurrent.Callable 接口,与 Runnable 接口类似,但可以返回对象或抛出异常。:Callable 接口使用泛型来定义其返回类型。Executors 类提供了一些有用的方法来在线程池的 Callable 中执行任务。由于 Callable 任务是并行的,我们必须等待它返回的结果。java.util.concurrent.Future 对象为我们解决了这个问题。线程池提交Callable任务后能让线程停止执行的有,返回一个Future对象。使用它,我们可以知道Callable任务的状态,并得到Callable返回的执行结果。Future 提供了 get() 方法,以便我们可以等待 Callable 结束并获取其执行结果。

3:什么是FutureTask?

FutureTask 是 Future 的一个基本实现,我们可以将它与 Executors 一起使用来处理异步任务。通常我们不需要使用 FutureTask 类,它只有在我们打算重写 Future 接口的一些方法并保持原有的基本实现时才变得非常有用。我们可以从它继承并覆盖我们需要的方法。

4:并发容器的实现方式是什么?

Java 集合类是快速失败的,这意味着当集合发生变异并且线程正在使用迭代器遍历集合时,迭代器的 next() 方法将抛出 ConcurrentModificationException。并发容器支持并发遍历和并发更新。主要的类是 ConcurrentHashMap、CopyOnWriteArrayList 和 CopyOnWriteArraySet。

5:什么是Executors类?

Executor 为 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类提供了一些实用方法。执行器可用于轻松创建线程池。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论