多线程相关面试题

一、线程有哪些状态?

        java线程分为6种状态:

                (1)新建(NEW) 

                (2)可运行( RUNNABLE)

                (3)阻塞(BLOCKED) 

                (4)等待(WAITING) 

                (5)超时等待(TIMED_WAITING) 

                (6)终结(TERMINATED) 

二、线程池的核心参数 

        (1)corePoolSize 核心线程数

                        最多保留的线程数

        (2)maximumPoolSize 最大线程数

                        核心线程 + 临时线程

        (3)keepAliveTime 空闲线程存活时间

                        针对临时线程

        (4)unit 时间单位

                        针对临时线程

        (5)workQueue 工作队列

                        阻塞队列

        (6)threadFactory 线程工厂

                        创建一个新线程时使用的工厂,可以给线程设置名字

        (7)handler 拒绝策略

                        1.AbortPolicy:丢弃任务并抛出RejectedExecutionException异 (常用)

                        2.DiscardPolicy:丢弃任务,但是不抛出异常

                        3.DiscardOldestPolicy:丢弃队列中最老的任务(也就是丢弃一个即将被执行的任务),并尝试再次提交当前任务

                        4.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务 

三、sleep 和 wait 的区别 

        共同点:wait() 、wait(long) 、sleep(long) 的效果都是让当前线程暂时放弃 cpu 的使用权,进入阻塞状态

        (1)方法归属不同

                        sleep(long) 是thread类中的静态方法

                        wait() 、wait(long) 是object类中的方法

        (2)醒来的时机不同

                        执行 sleep(long) 、wait(long) 的线程都会在等待相应的时间后醒来

                        wait(long) 、wait() 还可以被 notify() 或 notifyAll() 唤醒,wait() 如果不唤醒就会一直等下去

        (3)锁特性不同

                        wait 方法的调用必须先获取 wait 对象的锁,而 sleep 不用

                        wait方法执行后会释放对象锁,允许其它线程获得该对象锁,而 sleep 如果在 synchronized 代码块中执行,并不会释放对象锁

四 、lock 和 synchronized 的区别

        (1)语法层面

                        synchronized 是关键字,在 jvm 层面上, c++ 语言实现

                        Lock 是接口 ,java 语言实现

                        使用 synchronized 时,退出同步代码块会自动释放锁,而使用 Lock 时,需要手动调用 lock() 、unlock() 方法加锁和释放锁

        (2)功能层面

                        Lock 和 synchronized 均属于悲观锁,都具备基本的互斥、同步、锁重入功能

                        Lock 提供了很多 synchronized 不具备的功能,例如获取等待状态、公平锁、可打断、可超时、多条件变量等

                        Lock 有适合不同场景的实现,如 ReentrantLock,ReentrantReadWriteLock

        (3)性能层面

                        在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能并不差

                        在竞争激烈时,Lock 的实现通常会提供更好的性能

五、volatile 能否保证线程安全 

        (1)线程安全要考虑三个方面:可见性、有序性、原子性

                        1.可见性指:一个线程对共享变量修改,另一个线程能看到最新的结果

                        2.有序性指:一个线程内代码按编写顺序执行

                        3.原子性指:一个线程内多行代码以一个整体运行,期间不能有其它线程的代码插队 

        (2)volatile 能够保证共享变量的可见性、有序性,但并不能保证原子性

六、java 中的悲观锁与乐观锁 

        (1)悲观锁的代表:syschronized 和 lock

                        1.其核心思想是:线程只有占有了锁,才能去操作共享变量,每次只有一个线程占锁成功,获取锁失败的线程,都得停下来等待

                        2.线程从运行到阻塞,再从阻塞到唤醒,,设计线程上下文切换,如果频繁发生,影响性能

                        3.实际上,线程在获取 synchronized 和 lock 锁时,如果锁已经被占用,都会做几次重试操作,减少阻塞的机会

        (2)乐观锁的代表是:AtomicInteger ,使用 CAS 来保证原子性

                        1.其核心思想是:无需枷锁,每次只有一个线程能成功修改共享变量,其它失败的线程不需要停止,不断重试直至成功

                        2.由于线程一直运行,不需要阻塞,因此不涉及线程上下文切换

                        3.它需要多核 cpu 支持,且线程数不应超过 cpu 核数

七、Hashtable 和 ConcurrentHashMap 的区别 

        (1)Hashtable 和 ConcurrentHashMap 都是线程安全的 Map 集合

        (2)Hashtable 并发度低,整个 Hashtable 对应一把锁,在同一时刻,只能有一个线程能操作它

        (3)jdk 1.8 之前,ConcurrentHashMap 使用的是 Segment + 数组 + 链表的结构,每个 Segment 对应一把锁,如果多个线程访问不同的 Segment ,则不会冲突

        (4)jdk 1.8 开始,ConcurrentHashMap 将数组的每个头节点作为锁,如果多个线程访问的头节点不同,则不会冲突

八、谈一谈你对 ThreadLocal 的理解 

        (1)ThreadLocal 可以实现线程间的隔离,让每个线程各用各的资源对象,避免争用引发的线程安全问题 

        (2)ThreadLocal 同时实现了线程内的资源共享

        (3)其原理是,每个线程内有一个 ThreadLocalMap 类型的成员变量,用来存储资源对象 

                        1.调用 set 方法,就是以 ThreadLocal 自己作为 key ,资源对象作为 value 放入当前线程的 ThreadLocalMap 集合中

                        2.调用 get 方法,就是以 ThreadLocal 自己作为 key ,到当前线程中查找关联的资源值

                        3.调用 remove 方法,就是以 ThreadLocal 自己作为 key ,移除当前线程关联的资源值 

九、为什么 ThreadLocalMap 中的 key (即 ThreadLocal)要设计为弱引用 

        (1)Thread 可能需要长时间运行(比如线程池中的线程),如果 key 不再使用,需要在内存不足(GC)时释放其占用的内存

        (2)但是 GC 仅是让 key 的内存释放,后续还要根据 key 是否为 null 来进一步释放值的内存,其释放的时机有:

                        1.获取 key 时,发现 key 为 null

                        2.set key 时,会使用启发式扫描,清除临近的 null key 启发次数与元素个数,是否发现 null key 有关

                        3.remove 时(推荐),因为一般使用 ThreadLocal 时,都把它作为静态变量,因此 GC 无法回收 

 

                        

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值