当前位置: 首页 > 后端技术 > Java

Java多线程面试题

时间:2023-04-01 18:19:47 Java

1.什么是线程?线程是操作系统能够进行操作调度的最小单位。它包含在一个流程中,是流程中的实际操作单元。程序员可以使用它进行多处理器编程,您可以使用多线程来加速计算密集型任务。例如,如果一个线程完成一项任务需要100毫秒,那么十个线程完成任务只需要10毫秒。Java在语言层面对多线程提供了极好的支持,这也是一个很好的卖点。有关更多详细信息,请单击此处。2、线程和进程有什么区别?线程是进程的子集。一个进程可以有多个线程,每个线程并行执行不同的任务。不同的进程使用不同的内存空间,所有的线程共享同一个内存空间。不要和栈内存混淆,每个线程都有单独的栈内存用于存放本地数据。3、Java中如何实现线程?在语言层面有两种方式。java.lang.Thread类的实例是一个线程但是需要调用java.lang.Runnable接口来执行。由于thread类本身就是被调用的Runnable接口,所以可以继承java.lang.Thread类或者直接调用Runnable接口重新编写run()方法来实现线程。4.使用Runnable还是Thread?这个问题是上一个问题的后续问题。大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程。问题是,哪种方法更好?应该在什么情况下使用?这个问题很容易回答,如果你知道Java不支持类的多重继承,但是允许你调用多个接口。所以如果要继承其他类,当然要调用Runnable接口。5.Thread类中的start()和run()方法有什么区别?这个问题经常被问到,但还是可以区分面试官对Java线程模型的理解程度。start()方法用于启动新创建的线程,start()内部调用了run()方法,不同于直接调用run()方法。当你调用run()方法时,它只会在原始线程中被调用。如果没有启动新线程,start()方法将启动一个新线程。6.Java中的Runnable和Callable有什么区别?Runnable和Callable都表示要在不同线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5才加入的。它们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回一个加载了计算结果的Future对象。7.Java中的CyclicBarrier和CountDownLatch有什么区别?CyclicBarrier和CountDownLatch都可以用来让一组线程等待其他线程。与CyclicBarrier不同,CountdownLatch不能重复使用。8.什么是Java内存模型?Java内存模型指定并指导Java程序在不同的内存体系结构、CPU和操作系统之间确定性地运行。在多线程的情况下尤为重要。Java内存模型提供了一种保证,即一个线程所做的更改可以被其他线程看到,并且它们之间存在一种先发生后发生的关系。这种关系定义了一些规则,让程序员在并发编程时可以更清晰地思考。例如,happens-before关系保证线程中的代码可以顺序执行,这称为程序顺序规则。对于同一个锁,一个解锁操作必须发生在另一个时间上更晚发生的锁操作之前,这也称为监视器锁规则。前面对volatile的写操作先于后面的volatile的读操作,也叫volatile变量规则。线程中的任何操作都必须在线程的start()调用之后调用,也称为线程启动规则。根据线程终止规则,线程的所有操作都将在线程终止之前执行。对象的终结操作必须在对象构造完成后完成,也称为对象终结规则。可传递性9.Java中的volatile变量是什么?volatile是一种特殊的修饰符,只能被成员变量使用。在Java并发程序中没有同步类的情况下,多线程对成员变量的操作对其他线程是透明的。volatile变量可以保证下一次读操作发生在上一次写操作之后,也就是上一题中的volatile变量规则。10.什么是线程安全?Vector是线程安全类吗?如果你的代码在一个同时运行多个线程的进程中,那么这些线程可能会同时运行这段代码。如果每次运行的结果都和单线程运行的结果一样,并且其他变量的值都和预期的一样,就是线程安全的。一个线程安全的计数器类的同一个实例对象即使被多个线程使用也不会被误算。显然,您可以将集合类分为两组,线程安全的和非线程安全的。Vector使用同步的方式来实现线程安全,而与之类似的ArrayList并不是线程安全的。这里给大家推荐一个架构学习交流圈。交流学习假鑫:1253431195(内含大量面试题及答案)将分享一些资深架构师录制的录像:有Spring、MyBatis、Netty源码分析,高并发、高性能、分布式、微服务架构原理、JVM性能优化、分布式架构等已经成为架构师必备的知识体系。还可以领到免费的学习资源,至今受益匪浅。11.什么是Java中的竞争条件?举个例子。竞态条件会导致并发运行的程序出现错误。当多个线程竞争某些资源时,就会出现竞争条件。如果先执行的程序竞争失败,预定后执行,那么整个程序就会出现一些不确定的bug。由于线程之间的随机争用,此类错误很难发现和重现。12.如何在Java中停止一个线程?Java提供了丰富的API但没有提供停止线程的API。JDK1.0最初有一些控制方法,如stop()、suspend()和resume(),但由于潜在的死锁威胁,它们在后续的JDK版本中被弃用,JavaAPI的设计者也没有提供兼容和线程安全的方法停止线程。当执行run()或call()方法时,线程会自动结束。如果要手动结束一个线程,可以使用volatile布尔变量退出run()方法的循环或者取消任务来中断线程。13.Java中的信号量是什么?Java中的Semaphore是一种新的同步类,是一种计数信号。从概念上讲,信号量维护一组权限。每个acquire()都会阻塞,直到许可可用,然后在必要时获取许可。每个release()添加一个许可,可能会释放一个阻塞的获取者。然而,信号量并没有使用实际的许可证对象,而是只计算可用许可证的数量并采取相应的行动。信号量常用于多线程代码中,例如数据库连接池。14.如果提交任务,线程池队列已满。当它发生时会发生什么?这是一个棘手的问题,许多程序员会假设任务将阻塞,直到线程池队列空闲为止。事实上,如果无法安排任务执行,则ThreadPoolExecutor的submit()方法将抛出RejectedExecutionException。15、Java线程池中的submit()和execute()方法有什么区别?这两种方法都可以向线程池提交任务。execute()方法的返回类型为void,定义在Executor接口中,而submit()方法可以返回保存计算结果的Future对象,定义在ExecutorService接口中,扩展了Executor接口,ThreadPoolExecutor和ScheduledThreadPoolExecutor等其他线程池类都有这些方法。16、什么是阻断法?阻塞方法意味着程序将等待方法完成而不做其他事情。ServerSocket的accept()方法是等待客户端连接。这里的阻塞是指在调用结果返回之前,当前线程会被挂起,直到得到结果才会返回。此外,还有在任务完成之前返回的异步和非阻塞方法。17.Swing是线程安全的吗?为什么?你可以肯定的回答Swing不是线程安全的,但是你应该解释为什么,即使面试官没有问你为什么。当我们说swing不是线程安全的时,我们通常指的是它的组件。这些组件不能在多线程中修改。所有对GUI组件的更新都必须在AWT线程中完成,Swing提供了同步和异步回调方法。更新。这里给大家推荐一个架构学习交流圈。交流学习假鑫:1253431195(内含大量面试题及答案)将分享一些资深架构师录制的录像:有Spring、MyBatis、Netty源码分析,高并发、高性能、分布式、微服务架构原理、JVM性能优化、分布式架构等已经成为架构师必备的知识体系。还可以领取免费的学习资源,受益匪浅。18.Java中的invokeAndWait和invokeLater有什么区别?这两个方法由SwingAPI提供给Java开发人员从当前线程而不是事件派发线程更新GUI组件。.InvokeAndWait()同步更新GUI组件,例如进度条。一旦更新了进度,进度条也应该相应地改变。如果进度被多个线程跟踪,则调用invokeAndWait()方法请求事件派发线程相应地更新组件。invokeLater()方法异步调用更新组件。19.SwingAPI中哪些方法是线程安全的?这个问题还提到了摆动和线程安全。虽然组件不是线程安全的,但还是有一些方法可以被多线程安全调用,比如repaint()、revalidate()。JTextComponent的setText()方法和JTextArea的insert()和append()方法也是线程安全的。20.如何在Java中创建不可变对象?这个问题似乎与多线程无关,但不变性有助于简化已经很复杂的并发程序。不可变对象可以在不同步的情况下共享,减少并发访问对象的同步开销。但是,Java没有@Immutable注解。要创建不可变类,必须实现以下步骤:通过构造函数初始化所有成员,不为变量提供setter方法,并将所有成员声明为private,不允许直接访问这些成员,在getter方法中,不直接返回对象本身,而是克隆对象并返回对象的副本。