多线程面试--基础篇 Bertha 。 2022-03-27 08:20 220阅读 0赞 # 1.多线程概念 # 运行程序会创建一个进程,但OS调度(操作调度)的最小单位是线程 一个普通的java程序(比如main函数)至少包含6个的线程: (Monitor Ctrl-Break:监听中断信号 Attach Listener:获取内存dump,线程dump Signal Dispatcher:z将信号分给jvm的线程 Finalizer:调用对象的finalizer 方法 Reference Handler:清除Reference main:程序的主入口) # 2.为什么要用线程? # 1.可以充分的利用多处理核心 2.可以有更快的响应时间 # 3.启动线程和退出线程 # **创建线程的方法** 一,可以继承Thread类, 二,可以实现Runnable接口 **启动线程** thread类的start()方法,(run()方法只是类里面的普通方法,不要想混了,想的过于复杂) **线程完成** 一是,run()方法执行完成了 二是,抛出了一个未处理的异常导致线程提前的结束了 # 4.不安全的取消 # **单独使用一个取消标志位** 在java中有一些已经过期了的api.有很大的副作用的取消方法,比如stop(),suspend(),resume()方法,容易导致死锁或者数据不一致 # 5.如果安全的终止线程呢? # **使用线程中断的方法** interrupt()中断线程,他的本质是线程的中断标志位设置为true.其他线程会告知一声需要中断的线程,不过是否真正的进行中断由线程自己决定 (有java的中断机制可知,java里没有抢占式任务,只有协作式任务) 抢占式任务就是类似windows系统里的可以用任务管理器"杀掉"的任务,协作式任务反之 # 6.处理不可中断的阻塞 # 像inputstream read,inputstream write等阻塞方法,是不会理会中断的,而关闭底层的套接字socket.close()会抛出socketException 死锁状态不响应中断的请求,这个必须重启程序,修改错误。 # 7.如何让我们的代码既可以响应普通的中断,又可以关闭底层的套接字呢? # 一,覆盖线程的interrupt方法 二,在处理套接字异常时,再用super.interrupt()自行中断线程 # 8.线程都有哪些状态? # 1.新创建 线程刚被创建,还没有调用start方法的时候 2.可运行(RUNNABLE) 运行状态,(为什么称为可运行状态,是因为是不是正在运行完全由cpu决定) 3.被阻塞(BLOCKING) 阻塞,线程被阻塞于锁 4.等待/计时等待(WAITING) 等待某些条件 5.被终止 线程执行完毕 # 9.线程的优先级 # 线程里的优先级由成员变量priority控制,范围是1-10,数字越高优先级越高,缺省(系统默认状态)为5 在创建线程时,setPriority()可以设置优先级,不过,并不能指望他发挥作用. # 10.什么是Daemon线程 # Daemon线程是守护型线程,如果程序里面没有非Daemon线程时,java程序就会退出,一般用不上,也不建议平时开发时使用; (当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。) # 11.说说看你对线程常用方法的理解 # 线程里面常用的方法, 比如 run()方法只是一个普通的方法,和其他的类的实例方法没有任何区别, start()方法是用于开启线程的 sleep()方法休眠多长时间,这个方法不会释放锁,我们使用这个方法的时候,要放在同步代码快的外面. vield()方法,让当前线程让出cpu占有权,当前线程变成可运行状态,(下一时刻任何可能被cpu选择,不会释放锁) wait()方法,让线程进入等待状态, notify()/notifyAll()方法,唤醒**一个**线程/唤醒全部线程,notify() 唤醒一个线程,唤醒哪一个完全看cpu的心情(谨慎使用),所以一般推荐使用notifyAll()方法 # 12.volatile和synchronized5 # **多个线程同时访问一个共享的变量的时候,每个线程的工作内存有这个变量的一个拷贝,但是变量本身还是保存在共享内存中。** **volatile关键字**只是保证了字段的可见性,并不是线程安全的,没有操作的原子性,它是对着个变量的访问必须要从共享内存刷新一次.只能保证读的一致; 常用于:一个线程写,多个线程读的环境 **synchronized关键字**可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性,又被称为内置锁机制。(Synchronized的类锁和对象锁,本质上是两把锁,类锁锁的是每一个类的class对象,对象锁锁的是当前对象实施) # 12.等待和通知机制 # **等待方** 1.获取对象锁 2.判断条件是否满足,否,则调用对象的wait方法(被通知后也需要检查条件是否满足) 3.满足后执行相关操作 Synchronized(对象){ While(条件不满足){ 对象.wait() } 业务逻辑处理 } **通知方** Synchronized(对象)\{ 业务逻辑处理,改变条件 对象.notify/notifyAll \} 1、 获得对象的锁; 2、 改变条件; 3、 通知所有等待在对象的线程 # 13.管道输入输出流 # 管道输入输出流(文件输入输出,网络输入输出也是)用于线程中间的数据传递,传输媒介的内存 pipedOutputStream/input 面向的字节 pipedReader/Writer 面向的是字符 只适合线程间一对一的通信,适用范围较狭窄。 # 14.join方法 # 线程A执行了thread.join()后,线程A只有在等待thread线程终止了以后,线程A中在join后面的语句才会继续执行 # 15.ThreadLocal # 本质是个map map的键就是每个线程对象,值就是每个线程所拥有的值 常用方法: initialValue(),get(),set(),remove() # 16性能问题 # 实现串行化、无锁化、异步化编程是趋势之一 **注意:** 编码时候不要考虑性能优化的事情,先正确实现业务,发现性能不行,这个时候再来考虑性能优化。 # 17等待超时模式 # 调用一个方法时等待一段时间(一般来说是给定一个时间段),如果该方法能够在给定的时间段之内得到结果,那么将结果立刻返回,反之,超时返回默认结果。
还没有评论,来说两句吧...