面试题一重点

实现线程的三种方式?
 1:继承Thread类,覆写run方法,创建实例对象,Thread可以直接调用start来启动线程
 2:创建runnable实现类,在类中覆写run方法,需要将实例作为参数传递给Thread类有参构造创建线程对象,
      再通过Thread类来调用start方法。
 3:创建callable接口实现类,类中覆写call方法,创建实例对象,将其作为参数传递给FutureTask类,然后有参构造FutureTask
      对象,再通过这个对象来传递给Thread类的有参构造创建线程对象,再调用start方法来启动线程。
start()和run()的区别
   都需要实现run方法,并且最后都是用start方法来启动线程
runable和callable的区别
   callable有返回值,并且使用FutureTask来进行封装
2.Synchronized和lock的区别
   相同:都是解决并发编程中的线程安全问题
   不同:Synchronized是一个关键字 在线程发生异常时,会自动释放锁,不会发生异常死锁,可重入,不可判断,非公平锁
       Lock是一个接口,它基于CAS乐观锁来实现的,在异常时不会自动释放锁,我们需要在finally中释放锁(需要手动释放锁)
       是可重入,可判断的,可手动指定公平锁或者非公平锁
3.线程的生命周期 (new,runnable,running,Blocked,Dead)
    sleep和wait的区别
    第一:   sleep方法是Thread类的静态方法,wait方法是Object类的方法
       第二:sleep方法不会释放对象锁,wait方法会释放对象锁
      第三:sleep方法必须捕获异常,wait方法不需要捕获异常
          第四:wait需要被唤醒notify
          sleep和wait,被唤醒,进入runnable状态
4.synchronized锁的原理,JDK1.6之后做了什么样的优化
    是基于JVM内置锁实现,通过内部对象Monitor(监视器锁)实现 ,监视器锁的实现依赖 底层操作系统的Mutex lock(互斥锁)实现
    它是一个重量级锁性能较低,涉及到用户态到内核态的切换,会让整个程序性能变得很差
    JDK1.6后增加了锁升级的过程,依次为无锁,偏向锁,轻量级锁,重量级锁。而且还增加了锁粗化,锁消除等策略,这就节省了锁操作的开销,
        提高了性能(没有线程抢占资源无锁,轻量级锁自旋10次变成重量级锁)
5.乐观锁的使用场景(数据库,ES)   version   Atomic  
场景一:ES中对version的控制并发写。
场景二:数据库中使用version版本号控制来防止更新覆盖问题。
场景三:原子类中的CompareAndSwap操作
13.Synchronized和volatile的区别
    相同点:都是解决并发编程中线程安全问题
    不同点:
           第一:volatile的实现原理,是在每次使用变量时都必须从主存中加载,修改变量后都必须立马同步到主存;
               synchronized的实现原理,则是锁定当前变量,让其他线程处于阻塞状态
            第二:volatile只能修饰变量,
               synchronized用在修饰方法和同步代码块中
           第三:volatile修饰的变量,不会被编译器进行指令重排序,
               synchronized不会限制指令重排序
           第四:volatile不会造成线程阻塞,高并发时性能更高,
               synchronized会造成线程阻塞,高并发效率低
           第五:volatile不能保证操作的原子性,因此它不能保证线程的安全,
               synchronized能保证操作的原子性,保证线程的安全

6.什么是CAS   比较并交换
    乐观锁   compare and swap的缩写
非阻塞同步:基于冲突检测的乐观并发策略,通俗地说,就是先进行操作,如果没有其他线程争用共    享数据,那操作就成功了;
        如果共享数据有争用,产生了冲突,那就再采取其他的补偿措施(最常见    的补偿措施就是不断地重试,直到成功为止),
7.AtomicInteger怎么保证并发线程安全性?  乐观锁  CAS
    通过CAS操作原理来实现的  比较并交换
8.什么是乐观锁,什么是悲观锁,什么是重入锁,什么是自旋锁,什么是阻塞锁
     比较并交换,不锁定资源
     每次去拿数据的时候都会认为别人会修改数据,所以每次都会上锁,阻止别人来拿数据,直到悲观锁被释放。
    允许同一个线程多次获取同一把锁,是为可重入锁
    是一种状态,当一个线程尝试去获取锁时,如果这个锁已经被占用了,该线程就处于等待状态,并且隔一段时间再次尝试去获取
    阻塞,指的是当一个线程尝试获取锁失败了,线程就就进行阻塞,这是需要操作系统切换CPU状态的
9.你用过JUC包中的类吗?说几个 Lock ConcurrentHashMap AtomicInteger
    Lock锁体系 ,ConcurrentHashMap ,Atomic原子类,
10.ThreadLocal的作用  
    叫做线程本地变量,它是为了解决线程安全问题的,它通过为每个线程提供一个独立的变量副本,
    来解决并发访问冲突问题 - 简单理解它可以把一个变量绑定到当前线程中,达到线程间数据隔离目的。
11.ThreadLocal的原理 ThreadLocalMap
    ThredLocal是和当前线程有关系的,每个线程内部都有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,
    它用来存储每个线程中的变量副本,key就是ThreadLocal变量,value就是变量副本。
12.ThreadLocal的使用场景 SecurityContextHolder、RequestContextHolder  Zuul-RequestContext
     比如在spring security中,我们使用SecurityContextHolder来获取SecurityContext,比如在springMVC中,
    我们通过RequestContextHolder来获取当前请求,比如在 zuul中,我们通过ContextHolder来获取当前请求

14.线程池的作用,常用的线程池有几种?
    主要作用是控制并发数量,线程池的队列可以缓冲请求
    线程池可以实现线程的复用效果
    使用线程池能管理线程的生命周期
4种
   CachedThreadPool:可缓存的线程池,它在创建的时候,没有核心线程,线程最大数量是Integer最大值,最大空闲时间是60S
   FixedThreadPool:固定长度的线程池,它的最大线程数等于核心线程数,此时没有最大空闲时长为0
   SingleThreadPool:单个线程的线程池,它的核心线程和最大线程数都是1,也就是说所有任务都串行的执行
   ScheduledThreadPool:可调度的线程池,它的最大线程数是Integer的最大值,默认最长等待时间是10S,它是一个由延迟执行和周期执行的线程池
15.线程池的执行流程
 核心线程-->排队-->非核心线程-->拒绝策略
16.线程池构造器的7个核心参数
int corePoolSize,               核心线程数
int maximumPoolSize,      最大线程数
long keepAliveTime,         线程的空闲有效时间   
TimeUnit unit,                  线程的空闲有效时间单位    
BlockingQueue<Runnable> workQueue,    工作队列
ThreadFactory threadFactory,                 线程工厂
RejectedExecutionHandler handler        拒绝策略(容错方案)
17.线程池中的最大线程数  
考虑CPU核数,并发数量综合来考虑
18.EurekaClient拉取注册表&心跳续约用到了什么技术来实现的?
  ScheduledThreadPoolExecuto 带定时任务的线程池

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值