接做网站的,青岛网站设计哪家公司,洛可可设计公司招聘,拓者设计吧首页注意#xff1a;文章若有错误的地方#xff0c;欢迎评论区里面指正 #x1f36d;  系列文章目录 面试题分享之Java集合篇#xff08;三#xff09;  面试题分享之Java集合篇#xff08;二#xff09;  面试题分享之Java基础篇#xff08;三#xff09;  前言 今天给小… 注意文章若有错误的地方欢迎评论区里面指正   系列文章目录 面试题分享之Java集合篇三  面试题分享之Java集合篇二  面试题分享之Java基础篇三  前言 今天给小伙伴们分享我整理的关于Java并发的一些常见面试题这期涉及到线程的一些知识所以要求小伙伴有一些操作系统的知识不清楚也不要紧也不是什么很难的知识点。 一、什么是线程什么是进程 
线程线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流一个进程中可以并发多个线程每条线程并行执行不同的任务。进程进程是操作系统分配资源的基本单位它是程序在计算机上的一次执行活动。当系统为一个程序分配资源后该程序就成为一个独立的进程。 面试官追问线程跟进程的区别是什么  线程是进程划分成的更小的运行单位。独立性进程是独立的拥有独立的内存空间和系统资源而线程是依赖进程的多个线程共享其所属进程的内存空间和资源。开销进程的创建和销毁开销较大因为需要为其分配和回收系统资源而线程的创建和销毁开销较小。切换速度由于线程的上下文信息相对较少因此线程间的切换速度通常比进程间的切换速度快。通信与数据共享进程间的通信和数据共享相对困难需要通过特定的机制来实现而线程间的通信和数据共享相对容易因为它们共享其所属进程的内存空间和资源。并发性进程和线程都可以实现并发执行但线程通常用于实现更细粒度的并发操作。在一个多核或多处理器的系统中多个进程可以并行执行而在一个进程中多个线程也可以并行执行如果处理器支持多线程。 二、说一下线程的生命周期它有几种状态 
线程的生命周期包含五个阶段即五种状态分别是 新建状态New新创建了一个线程对象但还没有调用start()方法。在这个阶段线程只是被分配了必要的资源并初始化其状态。  就绪状态Runnable线程对象创建后其他线程比如main线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中变得可运行只等待获取CPU的使用权。换句话说线程已经做好了执行的就绪准备表示可以运行了但还不是正在运行的线程。  运行状态Running当就绪的线程被调度并获得CPU资源时便进入运行状态开始执行run()方法的线程执行体。在这个阶段线程正在执行其任务。  阻塞状态Blocked在运行状态的时候可能因为某些原因导致运行状态的线程变成了阻塞状态。阻塞状态是线程因为某种原因放弃CPU使用权暂时停止运行。阻塞的情况可能包括 等待阻塞运行的线程执行wait()方法该线程会释放占用的所有资源JVM会把该线程放入“等待池”中。其他阻塞运行的线程执行sleep()或join()方法或者发出了I/O请求时JVM会把该线程置为阻塞状态。阻塞于锁线程试图获取某个锁但该锁当前被其他线程持有。直到线程进入就绪状态才有机会转到运行状态。  死亡状态Dead当线程退出run()方法时线程就会自然死亡处于终止或死亡状态也就结束了生命周期。  
这五个状态构成了线程从创建到消亡的完整生命周期。 
三、说一下你对守护线程的了解 
守护线程即Daemon线程是一种支持型线程因为它主要被用作程序中后台调度以及支持性工作。这意味着当一个Java虚拟机中不存在非Daemon线程的时候Java虚拟机将会退出因此在守护线程中执行涉及I/O操作的任务可能会导致数据丢失或其他不可预测的问题。可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程。 面试官追问如何使用守护线程使用时有什么要注意的 使用方法 创建线程首先你需要创建一个继承自Thread类的新线程或者实现Runnable接口的对象。  设置守护线程在调用start()方法之前通过调用线程的setDaemon(true)方法将其设置为守护线程。  启动线程调用线程的start()方法启动线程。  
示例 
public class DaemonThreadExample extends Thread{public DaemonThreadExample() {// 默认构造函数}Overridepublic void run() {while (true) {// 守护线程执行的代码System.out.println(守护线程正在运行....);try {Thread.sleep(1000); // 暂停一秒} catch (InterruptedException e) {e.printStackTrace();// 如果守护线程被中断则退出循环break;}}}public static void main(String[] args) {// 创建守护线程对象DaemonThreadExample daemonThread  new DaemonThreadExample();// 设置为守护线程daemonThread.setDaemon(true);// 启动守护线程daemonThread.start();// 主线程执行其他任务例如休眠一段时间try {Thread.sleep(5000); // 主线程休眠5秒} catch (InterruptedException e) {e.printStackTrace();}// 当主线程结束时守护线程也会立即停止System.out.println(当主线程结束时守护线程停止.);}
} 
注意事项 设置守护线程的时机必须在调用线程的start()方法之前调用setDaemon(true)方法将其设置为守护线程。如果在调用start()方法之后调用setDaemon(true)则会抛出IllegalThreadStateException。  守护线程与前台线程守护线程主要是为前台线程服务的。当所有的前台线程都结束时JVM会立即停止此时守护线程也会被强制终止。因此守护线程不应该执行任何重要的或必须完成的任务。  避免在守护线程中执行I/O操作由于守护线程的生命周期是不确定的可能在任何时候被终止因此在守护线程中执行I/O操作可能会导致数据丢失或文件损坏等问题。  线程池中的守护线程如果你在使用线程池如ExecutorService并希望线程池中的线程是守护线程那么你需要确保在调用Executors的工厂方法创建线程池时传入的线程工厂ThreadFactory创建的线程是守护线程。但是Java的ExecutorService默认并不支持直接设置守护线程因为线程池通常用于执行重要的后台任务这些任务应该由前台线程来执行。  不要依赖守护线程完成关键任务由于守护线程的生命周期受前台线程的控制因此不应该依赖守护线程来完成关键任务或需要持久运行的任务。这些任务应该由前台线程来执行。  守护线程在Java编程中有多种应用场景这些场景通常涉及需要在后台运行的任务以支持其他线程或执行特定的服务,比如日志记录、定时任务、数据统计、垃圾回收等。 
给大家写一个日志记录的场景 
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class LogRecorder {private final ScheduledExecutorService scheduler;private final BufferedWriter logWriter;public LogRecorder(String logFilePath) throws IOException {// 创建一个单线程的守护线程池scheduler  Executors.newSingleThreadScheduledExecutor(r - {Thread thread  new Thread(r);// 设置为守护线程thread.setDaemon(true);return thread;});// 初始化日志文件的写入器logWriter  new BufferedWriter(new FileWriter(logFilePath, true));}// 启动日志记录任务public void startLogging() {// 每隔一段时间记录一条日志这里假设为每5秒scheduler.scheduleAtFixedRate(() - {try {// 模拟生成一条日志String logMessage  日志信息:   System.currentTimeMillis();logWriter.write(logMessage);logWriter.newLine();logWriter.flush();System.out.println(logMessage);} catch (IOException e) {e.printStackTrace();// 可以在这里处理异常例如重新打开文件或记录错误日志}}, 0, 5, TimeUnit.SECONDS);}// 停止日志记录任务并关闭文件写入器public void stopLogging() throws IOException {scheduler.shutdown(); // 停止任务调度logWriter.close(); // 关闭文件写入器}public static void main(String[] args) throws IOException {// 假设日志文件路径为logs/application.logString logFilePath  文件地址/xxx.log;LogRecorder logRecorder  new LogRecorder(logFilePath);// 启动日志记录任务logRecorder.startLogging();// 模拟主线程执行一些任务try {Thread.sleep(30000); // 主线程休眠30秒} catch (InterruptedException e) {e.printStackTrace();}// 停止日志记录任务并关闭文件写入器logRecorder.stopLogging();// 主线程结束由于守护线程的存在JVM不会立即关闭// 但由于我们调用了scheduler.shutdown()守护线程中的任务将不再执行System.out.println( 主线程结束停止写入日志.);}
} 
四、使用多线程可能带来什么问题 
在进行并发编程时如果希望通过多线程执行任务让程序运行得更快会面临非常多的挑战比如 
上下文切换的问题频繁的上下文切换会影响多线程的执行速度。死锁的问题受限于硬件和软件的资源限制问题在进行并发编程时程序的执行速度受限于计算机的硬件或软件资源。 面试官追问既然你提到了锁那么死锁产生的必要条件是什么  互斥条件Mutual Exclusion至少有一个资源必须处于非共享状态即一次只能被一个进程或线程占用。请求与保持条件Hold and Wait进程或线程至少需要持有一个资源并且在等待其他资源时不释放已占有的资源。不可剥夺条件No Preemption已分配给进程或线程的资源不能被强制性地剥夺只能由持有资源的进程或线程主动释放。循环等待条件Circular Wait存在一个进程或线程的资源申请序列使得每个进程或线程都在等待下一个进程或线程所持有的资源。 面试官继续追问那你说说Java多线程避免死锁有什么办法  按顺序获取锁当多个线程需要获取多个锁时为了避免死锁可以约定一个获取锁的顺序并且所有线程都按照这个顺序来获取锁。这样可以确保锁是以一致的顺序被请求和释放的。避免嵌套锁尽量减少锁的嵌套使用避免在持有锁的情况下再申请其他锁。如果必须使用多个锁尽量保证锁的获取顺序一致以避免死锁。使用定时锁或tryLock()Java提供了定时锁的机制即在尝试获取锁的时候设定一个等待的时间。如果在这个时间内未能获取到锁就主动放弃。另外可以使用tryLock()方法来尝试获取锁如果获取失败则不会阻塞可以继续执行其他逻辑或等待一段时间后重新尝试。使用并发工具类Java中的并发工具类如java.util.concurrent包下的类提供了许多高级并发工具如Semaphore、CountDownLatch、CyclicBarrier等这些工具可以帮助简化多线程编程并减少死锁的风险。避免线程持有锁的时间过长当一个线程持有一个锁并长时间不释放时会阻塞其他线程的访问并增加死锁的概率。因此需要尽量缩短线程持有锁的时间及时释放锁以便其他线程能够及时获取锁并继续工作。仔细设计资源申请顺序在设计多线程程序时要仔细考虑资源申请的顺序。如果多个线程都需要获取同一组资源可以考虑引入一个资源分配器通过分配器来按照一定的策略来分配资源避免资源的竞争。死锁检测和恢复虽然预防死锁是最好的策略但有时死锁仍然可能发生。在这种情况下可以使用死锁检测算法来及时发现死锁并采取必要的措施进行恢复如终止一个或多个进程或线程或者回滚到某个一致的状态。 面试官继续追问你能写一个Java死锁的案例吗 当两个或多个线程无限期地等待一个资源而这些资源又被其他线程持有时就会发生死锁。 
public class DeadlockExample {
/*
这个死锁大概思路
1、线程1拿到lock1休眠5s
2、线程1休眠后线程2拿到lock2
3、线程1休眠结束后。尝试拿lock2但是lock2被线程2占有
4、同理线程2休眠结束后尝试拿lock1但是lock1又被线程1占有
因此造成了死锁
*/public static void main(String[] args) {Object lock1  new Object();Object lock2  new Object();new Thread(() - {synchronized (lock1){System.out.println(Thread.currentThread().getName()已经获得a锁);try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()睡眠5ms结束);synchronized (lock2) {System.out.println(Thread.currentThread().getName()已经获得b锁);}}},线程1).start();new Thread(() - {synchronized (lock2) {System.out.println(Thread.currentThread().getName()  已经获得b锁);try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()睡眠5ms结束);synchronized (lock1) {System.out.println(Thread.currentThread().getName()  已经获得a锁);}}},线程2).start();}
} 
五、说一说sleep()、wait()、join()、yield()的区别 
在说这几个方法区别之前先给大家说一下什么锁池和等待池。 
1.锁池 
所有需要竞争同步锁的线程都会放在锁池中比如当前对象的锁已经被其中一个线程得到则其他线程需要在这个锁池进行等待当前面的线程释放同步锁后锁池中的线程去竞争同步锁当某个线程得到后会进入就绪队列进行等待cpu资源分配。 
2.等待池 
当我们调用wait方法后线程会放到等待池当中等待池的线程是不会去竞争同步锁。只有调用notify或notifyAll后等待池的线程才会开始去竞争锁notify是随机从等待池选出一个线程放到锁池而notifyAll是将等待池的所以线程放到锁池当中。 
sleep跟wait的区别 
sleep方法是Thread类的静态方法wait是Object类的本地方法sleep方法不会释放锁但是wait会释放锁而且会加入到等待队列中 sleep就是把cpu的执行资格和执行权释放出去不在运行此线程当定时时间结束后再取回cpu资源参与cpu的调度获取到cpu资源后就可以继续运行了。而如果sleep时该线程有锁那么sleep也不会释放这个锁而是把锁带着进入了冻结状态也就是说其他需要这个锁的线程根本不可能获取到这把锁。也就是无法执行程序。如果在睡眠期间其他线程调用了这个线程的interrupt方法那么这个线程也会抛出interruptexception异常返回这和wait是一样的。 3.sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。 4.sleep不需要被唤醒但是wait需要不指定时间需要被别人中断。 5.sleep一般用于当前线程休眠或者轮询暂停操作wait则多用于多线程之间的通信。 6.sleep会让出CPU执行时间并且强制上下文切换而wait不一定wait后还是有机会重新争夺锁继续执行的。 yield跟join的区别 
yield执行后线程直接进入就绪状态马上释放cpu的执行权但是依旧保留了cpu的执行资格所以有可能cpu下次进行线程调度还会让这个线程获取到执行权继续执行 
join执行后线程进入阻塞状态例如在线程B中调用线程A的join那么线程B会进入到阻塞队列直到线程A结束或中断线程 
给大家举一个简单的例子t1线程先睡4秒然后执行之后又调用了join使主线程进入阻塞直到t1线程执行完之后主线程才会执行。注意是主线程进入阻塞而不是t1阻塞 
public static void main(String[] args) throws InterruptedException {Thread t1   new Thread(new Runnable() {Overridepublic void run() {try {Thread.sleep(4000);}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()执行了。。。);}});t1.start();t1.join();System.out.println(Thread.currentThread().getName()执行了。。。);}/*打印结果
Thread-0执行了。。。 先执行
main执行了。。。 后执行
*/ 
六、知道线程中的 run() 和 start() 有什么区别吗 功能 run(): 这是Thread类中的一个方法用于定义线程要执行的任务。当你直接调用一个线程的run()方法时例如myThread.run()它会在当前线程通常是主线程中执行而不是在新的线程中。这意味着它不会启动一个新线程。start(): 这是Thread类中的另一个方法用于启动一个新线程来执行run()方法中的代码。当你调用start()方法时例如myThread.start()Java会创建一个新的线程并在该线程中调用run()方法。这意味着run()方法中的代码会在新的线程中执行。 执行上下文 直接调用run()代码在当前线程通常是主线程的上下文中执行。调用start()Java会创建一个新的线程并在该线程的上下文中执行run()方法中的代码。 返回值 run(): 它没有返回值即返回类型为void。start(): 它也没有返回值返回类型为void但它启动了一个新线程。 异常处理 如果你在run()方法中抛出一个未检查的异常例如RuntimeException并且你没有在该方法中捕获它那么它会在当前线程中直接抛出并且可能会导致程序崩溃除非有其他地方的代码捕获了该异常。如果你在start()方法中抛出一个异常那么它实际上是在调用start()的线程中抛出的而不是在新创建的线程中。这是因为start()方法是在当前线程中调用的而新线程是在start()方法内部创建的。 线程状态 当线程首次被创建时它的状态是NEW。当你调用start()方法时线程的状态变为RUNNABLE或BLOCKED、WAITING、TIMED_WAITING等具体取决于线程的行为。如果你直接调用run()方法而不是start()方法线程将不会被创建为单独的线程并且它的状态仍然是NEW尽管这在实际中并不常见因为通常你会在创建线程后立即调用start()。 总结你应该总是使用start()方法来启动一个新线程而不是直接调用run()方法。 七、说了这么多Java程序中如何保证多线程的安全 
原子性在Java中对基本数据类型的变量的读取和赋值操作是原子性操作即这些操作是不可被中断的要么都执行要么都不执行。可以用Java提供了java.util.concurrent.atomic包下的原子类如AtomicInteger、AtomicLong等这些类中的方法都是线程安全或者java.util.concurrent.locks 包下的 Lock 接口提供了比 synchronized 更灵活的锁机制包括可重入锁、读写锁、定时锁等可见性Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时它会保证修改的值会立即被更新到主存当有其他线程需要读取时它会去内存中读取新值 另外通过synchronized和Lock也能够保证可见性synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。 有序性在Java里面可以通过volatile关键字来保证一定的“有序性”。另外可以通过synchronized和Lock来保证有序性很显然synchronized和Lock保证每个时刻是只有一个线程执行同步代码相当于是让线程顺序执行同步代码自然就保证了有序性。 总结 
这期的面试题需要大家多理解多记多背先理解在背。好了今天的分享就到这喜欢的小伙伴记得三连欧 
参考文章并发编程JVM_ΘLLΘ的博客-CSDN博客 文章转载自: http://www.morning.dblfl.cn.gov.cn.dblfl.cn http://www.morning.wfzdh.cn.gov.cn.wfzdh.cn http://www.morning.tqsgt.cn.gov.cn.tqsgt.cn http://www.morning.lqffg.cn.gov.cn.lqffg.cn http://www.morning.lwcqh.cn.gov.cn.lwcqh.cn http://www.morning.qtrlh.cn.gov.cn.qtrlh.cn http://www.morning.skmpj.cn.gov.cn.skmpj.cn http://www.morning.huxinzuche.cn.gov.cn.huxinzuche.cn http://www.morning.slwfy.cn.gov.cn.slwfy.cn http://www.morning.qtsks.cn.gov.cn.qtsks.cn http://www.morning.yxbrn.cn.gov.cn.yxbrn.cn http://www.morning.zmtrk.cn.gov.cn.zmtrk.cn http://www.morning.dgfpp.cn.gov.cn.dgfpp.cn http://www.morning.rtsdz.cn.gov.cn.rtsdz.cn http://www.morning.mjbkp.cn.gov.cn.mjbkp.cn http://www.morning.tfrlj.cn.gov.cn.tfrlj.cn http://www.morning.rnzjc.cn.gov.cn.rnzjc.cn http://www.morning.lgmty.cn.gov.cn.lgmty.cn http://www.morning.etsaf.com.gov.cn.etsaf.com http://www.morning.kpzrf.cn.gov.cn.kpzrf.cn http://www.morning.mzzqs.cn.gov.cn.mzzqs.cn http://www.morning.sgmgz.cn.gov.cn.sgmgz.cn http://www.morning.c7493.cn.gov.cn.c7493.cn http://www.morning.qcymf.cn.gov.cn.qcymf.cn http://www.morning.ldzss.cn.gov.cn.ldzss.cn http://www.morning.zpdjh.cn.gov.cn.zpdjh.cn http://www.morning.hgtr.cn.gov.cn.hgtr.cn http://www.morning.grjh.cn.gov.cn.grjh.cn http://www.morning.nbrkt.cn.gov.cn.nbrkt.cn http://www.morning.hxftm.cn.gov.cn.hxftm.cn http://www.morning.lqlhw.cn.gov.cn.lqlhw.cn http://www.morning.rcjwl.cn.gov.cn.rcjwl.cn http://www.morning.rrgqq.cn.gov.cn.rrgqq.cn http://www.morning.dfltx.cn.gov.cn.dfltx.cn http://www.morning.ndynz.cn.gov.cn.ndynz.cn http://www.morning.kpfds.cn.gov.cn.kpfds.cn http://www.morning.zkgpg.cn.gov.cn.zkgpg.cn http://www.morning.tgmfg.cn.gov.cn.tgmfg.cn http://www.morning.qwfl.cn.gov.cn.qwfl.cn http://www.morning.drnjn.cn.gov.cn.drnjn.cn http://www.morning.jjwt.cn.gov.cn.jjwt.cn http://www.morning.xgjhy.cn.gov.cn.xgjhy.cn http://www.morning.xjqkh.cn.gov.cn.xjqkh.cn http://www.morning.btsls.cn.gov.cn.btsls.cn http://www.morning.jjtwh.cn.gov.cn.jjtwh.cn http://www.morning.ljbch.cn.gov.cn.ljbch.cn http://www.morning.jcxgr.cn.gov.cn.jcxgr.cn http://www.morning.qmbtn.cn.gov.cn.qmbtn.cn http://www.morning.bzfwn.cn.gov.cn.bzfwn.cn http://www.morning.zmtrk.cn.gov.cn.zmtrk.cn http://www.morning.jhxdj.cn.gov.cn.jhxdj.cn http://www.morning.rzcfg.cn.gov.cn.rzcfg.cn http://www.morning.wlddq.cn.gov.cn.wlddq.cn http://www.morning.tyjp.cn.gov.cn.tyjp.cn http://www.morning.dmcxh.cn.gov.cn.dmcxh.cn http://www.morning.fgqbx.cn.gov.cn.fgqbx.cn http://www.morning.qdlnw.cn.gov.cn.qdlnw.cn http://www.morning.ydnxm.cn.gov.cn.ydnxm.cn http://www.morning.tytly.cn.gov.cn.tytly.cn http://www.morning.lgznc.cn.gov.cn.lgznc.cn http://www.morning.tdwjj.cn.gov.cn.tdwjj.cn http://www.morning.cxryx.cn.gov.cn.cxryx.cn http://www.morning.qpxrr.cn.gov.cn.qpxrr.cn http://www.morning.rlpmy.cn.gov.cn.rlpmy.cn http://www.morning.burpgr.cn.gov.cn.burpgr.cn http://www.morning.mjpgl.cn.gov.cn.mjpgl.cn http://www.morning.fwkq.cn.gov.cn.fwkq.cn http://www.morning.amlutsp.cn.gov.cn.amlutsp.cn http://www.morning.hlzpb.cn.gov.cn.hlzpb.cn http://www.morning.pqfbk.cn.gov.cn.pqfbk.cn http://www.morning.hsjfs.cn.gov.cn.hsjfs.cn http://www.morning.rrcrs.cn.gov.cn.rrcrs.cn http://www.morning.nfcxq.cn.gov.cn.nfcxq.cn http://www.morning.wsnjn.cn.gov.cn.wsnjn.cn http://www.morning.fbbpj.cn.gov.cn.fbbpj.cn http://www.morning.kgtyj.cn.gov.cn.kgtyj.cn http://www.morning.dbrpl.cn.gov.cn.dbrpl.cn http://www.morning.nthyjf.com.gov.cn.nthyjf.com http://www.morning.byshd.cn.gov.cn.byshd.cn http://www.morning.mooncore.cn.gov.cn.mooncore.cn