java多线程面试集合(1)

17 篇文章 0 订阅
8 篇文章 0 订阅

1.并行和并发的区别

操作系统角度,线程是最小的执行单位

  • 并行同一时刻两个线程都在执行,这就要求要有两个cpu。
  • 并发就是 同一时刻,只有一个执行但是在一个时间段内,两个线程都执行了,并发依赖于CPU切换线程,因为线程切换时间极短,所以用户无感。

2.什么是进程和线程

一个进程包含了多个线程,多个线程共用堆和方法区资源,但是每个线程有自己的计数器和栈。
看线程基本知识,描述了两者区别

3.线程创建的方式

线程创建有3种方式,继承Thread类,实现Runnable接口,Callable接口(又返回值)

4.为什么调用start()方法时会执行run()方法,那怎么不直接调用run()方法?

因为jvm执行start方法时候,会先创建一条线程,由创建的线程去调用thread类的run方法,起到多线程效果,如果直接执行run方法,那么相当于还是运行在主线程中,起不到多线程作用了。

5.线程有哪些常用的方法

  1. 等待:wait()、wait(long timeout)、wait(long timeout,int nanos),join()
  2. 通知: notify()、notifyAll()
  3. 中断:interrupt(),isinterruputed()、interrupted()(检测是否中断,如果被中断,则会清楚标志)
  4. 让出优先权:yoeld()
  5. 休眠:sleep()

5.线程的几种状态

共六种状态

  1. new新建
  2. runnable运行就绪
  3. blocked阻塞
  4. waiting 等待
  5. timed_waiting 超时等待
  6. terminated死亡

6.什么是线程上下文切换

为了让用户感觉多个线程是在同时执行的, CPU 资源的分配采用了时间片轮转也就是给每个线程分配一个时间片,
线程在时间片内占用 CPU 执行任务。当线程使用完时间片后,就会处于就绪状态并让出 CPU 让其他线程占用,这
就是上下文切换。

7.守护线程了解吗?

Java中的线程分为两类,分别为 daemon 线程(守护线程)和 user 线程(用户线程)。
在JVM 启动时会调用 main 函数,main函数所在的线程就是一个用户线程。其实在 JVM 内部同时还启动了很多守护
线程, 比如垃圾回收线程。
那么守护线程和用户线程有什么区别呢?区别之一是当最后一个非守护线程束时, JVM会正常退出,而不管当前是否
存在守护线程,也就是说守护线程

8.线程有那些通信方式

在这里插入图片描述

9.ThreadLocal是什么

TheadLocal是一个线程本地变量,如果你创建了一个ThreadLocal变量,那么访问这些变量的每个线程都会有这一个变量的本地拷贝,多个线程操作变量时候,实际操作的是自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程的安全问题。
在这里插入图片描述

1.创建一个ThreadLocal线程变量
public static ThreadLocal<String> localVabile = new ThreadLocal<>();
2.写入
localVabile.set("共享资源";
3.读取,在任何一个地方读取的都是他写入的变量
localVabile.get()


10.在工作中如何使用的ThreadLocal

  • 用来做用户的上下文的存储。
  • 常用的数据库连接池,交给ThreadLocal进行管理,保障当前线程的操作都是同一个Connection。

11.ThreadLocal如何实现

查看ThreadLocal的set方法,发现是先获取当前的线程,在获取TheadLocalMap,然后再把这个元素放到map中

public void set(T value){
			//获取当前线程
			Thread t = Thread.currentThread();
			//获取ThreadLocalMap
			ThreadLocalMap map = getMap(t);
			//将当前元素存入
			if(map !=null){
			map。set(this,value);
}else{
createMap(t,value)
}

ThreadLocal实现的秘密都在这个 ThreadLocalMap了,
实现原理:

  • Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,每个线程都有一个属于自己的ThreadLocalMap。
  • TheadLocalMap内部维护着Entry数组,每个Entry代表一个完整的对象,key是弱引用的作用,value是每个ThreadLocal的泛型
  • 每个线程在往里面设置值的时候,都是往自己的ThreadLocalMap里存,读也是以某个ThreadLocal作为引用值,在自己的map里面找对应的值,从而实现了线程隔离。ThreadLocal本身不存值,它只是作为一个key来人线程往里面存取值。

12. ThreadLocal的内存泄漏

在jvm中,栈内存私有,存储了对象的引用,堆内存线程共享,存储了对象实例

ThreadLocalMap中使用的 key 为 ThreadLocal 的弱引用。
“弱引用:只要垃圾回收机制一运行,不管JVM的内存空间是否充足,都会回收该对象占用的内存。”
那么现在问题就来了,弱引用很容易被回收,如果ThreadLocal(ThreadLocalMap的Key)被垃圾回收器回收了,但
是ThreadLocalMap生命周期和Thread是一样的,它这时候如果不被回收,就会出现这种情况: ThreadLocalMap的
key没了,value还在,这就会造成了内存泄漏问题。使用完ThreadLocal后及时调用remove()方法释放空间。

key设计成弱引用同样是为了防止内存泄漏。
假如key被设计成强引用,如果ThreadLocal Reference被销毁,此时它指向ThreadLoca的强引用就没有了,但是此时key
还强引用指向ThreadLoca,就会导致ThreadLocal不能被回收,这时候就发生了内存泄漏的问题。

13.ThreadLocalMap了解吗

ThreadLocalMap虽然被叫做map,但是它没有实现Map接口,但是结构还是和HashMap类似的,主要就是关注的是两个元素:元素数组和散列方法

  • 元素数组:一个table数组,存储Entry类型的元素,Entry是ThreadLocal弱引用的作为key,Object作为value的结构。
  • 散列方法:散列方法就是把对应的key映射到table数组的相应下标,ThreadLocalMap用的是哈希取余法,取出key的threadLocalHashcode,然后和table数组长度减一一起计算
int i = key.threadLocalHashCode & (table.length - 1);

ThreadLocalmap

14.TheadLocalMap怎么解决Hash冲突的

我们都知道hashmap使用了链表来解决冲突,也就是所谓的链地址法。
ThreadLocalMap则是使用的是开放定址法,简单来说就是这个坑被人占了,那就接着找个空着的坑

15.ThreadLocalMap的扩容机制

在这里插入图片描述

16.父子线程怎么共享数据?

父线程不能使用TheadLocal来给子线程进行值传递,这个时候使用另一个类InheritableThreadLocal,再主线程的InheritablThreadLocal实例设置值,在子线程中就可以拿到

public class InheritableThreadLocalTest {
public static void main(String[] args) {
final ThreadLocal threadLocal = new InheritableThreadLocal();
// 主线程
threadLocal.set("不 技术");
//子线程
Thread t = new Thread() {
@Override
public void run()
{ super.run();
System.out.println(" 人三某 ," +
threadLocal.get());
}
};
t.start();
}
}
那原理是什么呢?
原理很简单,在Thread类里还有另外一个变量:
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
在Thread.init的时候,如果父线程的 inheritableThreadLocals 不为空,就把它赋给当前线程(子线程)的
inheritableThreadLocals 。
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

ps:给我一个一键三连加加油呢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值