多线程面试--基础篇

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等待超时模式

调用一个方法时等待一段时间(一般来说是给定一个时间段),如果该方法能够在给定的时间段之内得到结果,那么将结果立刻返回,反之,超时返回默认结果。

发布了53 篇原创文章 · 获赞 42 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42815122/article/details/86372417
今日推荐