并发

目录

多线程

并发框架

线程安全

并发容器和框架

Java中的锁

并发工具


 


多线程

  • java中有几种方法可以实现一个线程?

        继承Thead 和 实现Runnable, 其实Runnable也是用Thead对象这run里调用 Runnable的方法

  •   2.如何停止一个正在运行的线程?

      使用Thead的中断和设置共享变量,两者都需被停止的线程自己主动检查。

可以使用正在运行的线程,支持线程中断,那么可以使用线程中断的方法停止这个线程;通常是定义一个volatile的状态变量,在运行线程线程中读这个变量,其它线程中修改这个变量

  • notify()和notifyAll()有什么区别?

notify是随机唤醒一个等待某个资源的线程,进入就绪队列等待CPU的调度,notifyAll是唤醒所有的,进入就绪队列等待CPU调度

  • sleep()和 wait()有什么区别?

sleep()是当前正在运行的线程主动放弃CPU,进入睡眠状态,如果此时线程已经持有一个锁,则释放这个锁
wait()是等待其它其它线程对某个共享资源的锁释放,等待期间,仍然持有它已经获得的同步锁,这个就是典型的两个线程互相等待对方持有的资源以致死锁的原因

sleep不会放开锁 ,wait会放开。调用wait必须先获取锁,也就是要写在synchronized里面

  • 什么是Daemon线程?它有什么意义?

守护线程是后台线程,它通常属于低优先级的线程,守护用户线程,通常做一些垃圾清理的工作,比如GC。当所有的用户线程退出后,守护线程不会立即退出,还出执行一段时间,具体多少时间,有知道的告诉我。。。

  • java如何实现多线程之间的通讯和协作?

共享变量和锁

 

  • 什么是可重入锁(ReentrantLock)?

已经持有这把锁的对象可以再次加锁,内部会维护一个共享变量,加锁+1 解锁-1,为0时才能被别人抢占。 所以使用重复加锁也要重复解锁

Jvm负责跟踪对象被加锁的次数,线程第一次给线程加锁的时候,计数变为1,每当这个相同的线程在此对象上再次获得锁时候,计数会增加,每当任务离开时,计数递减,当计数为0时,锁被完全释放

  • 当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

不可进入synchroized修饰的方法

  • synchronized和java.util.concurrent.locks.Lock的异同?

 都是可重入锁,java后面优化后性能和功能差距不大,lock可以实现公平锁

  • 乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

乐观锁,每次操作时不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止
悲观锁是会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁可以使用volatile+CAS原语实现
悲观锁可以使用synchronize的以及Lock。

并发框架

  • SynchronizedMap和ConcurrentHashMap有什么区别?

 前者只是在方法上加入synchronized 锁的粒度很大 ,后者是在map的”桶“上加锁,如果两个线程操作不是一个”桶“则可以同时进行 。性能更好

  • CopyOnWriteArrayList可以用于什么应用场景?

 在写时复制。修改时不影响读,读多写少的情况。CopyOnWriteArrayList这个容器适用于多读少写…读写并不是在同一个对象上。在写时会大面积复制数组,所以写的性能差,在写完成后将读的引用改为执行写的对象

 

线程安全

  • 什么叫线程安全?servlet是线程安全吗?

线程安全:就是所有情况都在”掌控”之中,所有情况都是可以预料和可以接受的 。servlet不是线程安全,但是spring的编程模式让我们尽量远离线程安全问题。

  • 同步有几种实现方法?

synchronized , 锁 ,使用共享变量做标示线程自旋等待

  • volatile有什么用?能否用一句话说明下volatile的应用场景?

内存屏障,防止指令重排,保证可见性,一个线程的修改一定会被其他线程看见

遵循happens-before 场景 :修饰共享变量

 

  • 请说明下java的内存模型及其工作流程。
  • 为什么代码会重排序?

优化性能,操作是在栈上进行,可以连续操作同一个变量,减少弹入弹出操作

对cpu 的缓存行也友好

并发容器和框架

  • 如何让一段程序并发的执行,并最终汇总结果?

使用CyclicBarrier 和CountDownLatch都可以   可以用join,或者条件变量
使用CyclicBarrier 在多个关口处将多个线程执行结果汇总
CountDownLatch 在各线程执行完毕后向总线程汇报结果

  • 如何合理的配置java线程池?如CPU密集型的任务,基本线程池应该配置多大?IO密集型的任务,基本线程池应该配置多大?用有界队列好还是无界队列好?任务非常多的时候,使用什么阻塞队列能获取最好的吞吐量?

配置线程池时CPU密集型任务可以少配置线程数,大概和机器的cpu核数相当,可以使得每个线程都在执行任务
IO密集型时,大部分线程都阻塞,故需要多配置线程数,2*cpu核数
有界队列和无界队列的配置需区分业务场景,一般情况下配置有界队列,在一些可能会有爆发性增长的情况下使用无界队列。
任务非常多时,使用非阻塞队列使用cas操作替代锁可以获得好的吞吐量。

生产者负责notify,消费者需要wait,条件是有无元素​​​​​​​

  • 多读少写的场景应该使用哪个并发容器,为什么使用它?比如你做了一个搜索引擎,搜索引擎每次搜索前需要判断搜索关键词是否在黑名单里,黑名单每天更新一次

CopyOnWriteArrayList这个容器适用于多读少写…读写并不是在同一个对象上。在写时会大面积复制数组,所以写的性能差,在写完成后将读的引用改为执行写的对象​​​​​​​

Java中的锁

  • 如何实现乐观锁(CAS)?如何避免ABA问题?

    读取内存值
    比较内存值和期望值
    替换内存值为要替换值

    带参数版本来避免aba问题,在读取和替换的时候进行判定版本是否一致

  • 读写锁可以用于什么应用场景?

多读少写,读写锁支持多个读操作并发执行,写操作只能由一个线程来操作

读写锁适用于读操作>>写操作,同时允许多个线程同时读,读读允许,读写互斥,写写互斥。这样的场景比较常见,比如,一个文件,我们可以要求同时读,但是不能读写或者写写同时发生。缓存Cache也可以实现同时读,互斥写。对于lucene这样的文本检索系统,也可以使用读写锁实现更新索引文件上写锁,读取索引加读锁。

  • 什么时候应该使用可重入锁?

重入锁指的是在某一个线程中可以多次获得同一把锁,在线程中多次操作有锁的方法。​​​​​​​

1.公平锁
2.多路条件,比如我要实现5个线程的同步,A->B->C->D->E->A,可以使用一个Lock,5个Condition来控制5个线程的步调
3.实现轮询,中断的功能,只听说过,没用过。

  •  
  • 什么场景下可以使用volatile替换synchronized?

只需要保证共享资源的可见性的时候可以使用volatile替代,synchronized保证可操作的原子性一致性和可见性。
volatile适用于新值不依赖于就值的情形。

并发工具

  1. 如何实现一个流控程序,用于控制请求的调用次数?​​​​​​​
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值