并发编程面试题

最近一直在看并发编程的相关知识,所以从网上搜了一些面试题,自己尝试着去解答,来检验最近的学习情况:

1) 什么是线程?

线程是一个程序控制流,是cpu调度执行作业的最小单位,线程一般隶属于某个进程。

2) 线程和进程有什么区别?

进程是应用程序,是资源分配的最小单位,比如内存、硬盘,一个进程至少包含一个线程。

3) 如何在Java中实现线程?

继承Thread重写run、实现Runnable重写run、或者创建线程池

4) 用Runnable还是Thread?

最好用Runnable,因为java不支持多继承,如果任务继承了Thread就不能再继承其他父类

6) Thread 类中的start() 和 run() 方法有什么区别?

调用start方法,线程进入就绪状态,调用run就是调用Thread对象的普通方法,不会启动线程

7) Java中Runnable和Callable有什么不同?

runnable没有返回值,而且异常会报出来,callable有返回值,如果有异常会封装在callable中,

可以通过get获取

8) Java中CyclicBarrier 和 CountDownLatch有什么不同?

cyclicBarrier可以重复利用,而且到达后可以异步启动一个线程runnable,countDownLatch不可以重复利用

9) Java内存模型是什么?

为了屏蔽jvm与平台硬件的不兼容,所以java有主内存和工作内存,操作一个变量首先要从主内存加载到工作内存,

操作完成后,在刷新到主内存。

10) Java中的volatile 变量是什么?

volatile保证线程之间的可见性与禁止指令重排序。

写:一个线程修改了变量的值,会被强制刷新到主内存。读:一个线程会强制令工作内存的状态栏失效,然后从主内存

中读取,加载到工作内存。

禁止指令重排序,栅栏屏蔽

11) 什么是线程安全?Vector是一个线程安全类吗?

线程安全是指多个线程访问一个类,如果访问之后的结果和一个线程访问之后的结果相同,那么可以认为该类是线程安全的。

vector是线程安全的类,因为vector类加了表锁,同一时刻只允许一个线程访问类

12) Java中什么是竞态条件

竞态条件就是同一个时刻只能有一个线程访问资源

13) Java中如何停止一个线程?

调用interrupt方法

14) 一个线程运行时发生异常会怎样?

线程终止,抛出异常

15) 如何在两个线程间共享数据?

主内存、wait/notify、await/signal 

16) Java中notify 和 notifyAll有什么区别?

notify会随机唤醒一个阻塞的线程,notifyAll会唤醒所有阻塞的线程

17) 为什么wait, notify 和 notifyAll这些方法不在thread类里面?

因为锁是对象级别的,不是线程级别的

18) 什么是ThreadLocal变量?

threadLocal可以保证线程安全,通过空间换时间,Thread类上有个threadLocals变量,

threadLocal维护了Entry,entry中维护了threadlocal对象与需要保证线程安全的变量之间的映射关系,也就是说

每个线程都会将这个变量的副本维护到自己的线程对象上,是线程隔离的

19) 什么是FutureTask?

futureTask就是对runnable的包装,也实现了runnable和future接口,futureTask的run方法会调用被包装的runnable对象的call

如果成功则将结果包装到outcome字段,失败则将异常包装到outcome上,然后通过report返回,通过get方法可以阻塞获取

20) Java中interrupted 和 isInterruptedd方法的区别?

 

21) 为什么wait和notify方法要在同步块中调用?

 

22) 为什么你应该在循环中检查等待条件?

 

23) Java中的同步集合与并发集合有什么区别?

collections提供的静态方法同步集合会把方法放到synchronized代码块中,锁的粒度比较大

 

24) Java中堆和栈有什么不同?

堆是用来放内存对象,为所有线程共享,栈又来放置基本数据和引用地址,是线程私有的

25) 什么是线程池? 为什么要使用它?

线程池是用来维护线程的一个容器,使用线程池可以不用频繁的创建和销毁线程,提高cpu的利用率,

而且当任务提交给线程池时,可以直接使用线程池维护的线程处理,提高响应速度。

26) 如何写代码来解决生产者消费者问题?

 

27) 如何避免死锁?

死锁的四个条件:

1:独占资源,互斥条件

2:请求和保持,线程在占有一个资源后,又申请另外的独占资源

3:不可剥夺,线程占有的资源除非自己释放,否则不可被剥夺

4:循环等待,线程申请资源形成了一个环状等待

只有打破其中的一个条件,就不会出现死锁。

通常做法只要保证每个线程申请锁的顺序一致,就不会出现死锁

28) Java中活锁和死锁有什么区别?

死锁是因为线程占有一个独占资源,同时又申请其他的资源,形成了循环等待,每个线程都在阻塞。

活锁没有阻塞,但是会因为永远满足不了条件而不断循环执行。

29) 怎么检测一个线程是否拥有锁?

Thread.holdsLock

30) 你如何在Java中获取线程堆栈?

Thread.getAllStackTraces()

31) JVM中哪个参数是用来控制线程的栈堆栈小的

xns

32) Java中synchronized 和 ReentrantLock 有什么不同?

synchronized是内置锁,支持可重入,默认非公平,阻塞不可中断。

ReentrantLock是显示锁,更加灵活,支持可尝试获取锁,可中断获取锁,尝试带超时时间获取锁

33) 有三个线程T1,T2,T3,怎么确保它们按顺序执行?

join

34) Thread类中的yield方法有什么作用?

放弃cpu的执行权,重新分配时间片

35) Java中ConcurrentHashMap的并发度是什么?

jdk1.7 16  jdk1.8不在使用片段锁,而是采用表+单向链表+红黑树,将锁的粒度缩小至单向链表上

36) Java中Semaphore是什么?

信号量,可以控制并发线程的数量

37)如果你提交任务时,线程池队列已满。会时发会生什么?

如果最大线程大于核心线程,那么会创建新的线程处理任务,如果最大线程等于核心线程,那么

会启用reject策略

38) Java线程池中submit() 和 execute()方法有什么区别?

submit一般提交有返回值的callable,也可以提交runnable任务,提交到submit的任务,会被包装成FutureTask,然后当线程调用start后

会执行FutureTask方法的run,调用call或者run,抛异常会被捕捉,封装到outcome中,没有异常把结果封装到outcome中,然后返回,get可以

阻塞拿到结果。

execute没有包装,start后直接,cpu直接调用worker的run 方法,runWork 调用runnable的run,异常会抛出。

39) 什么是阻塞式方法?

get,调用方法时,会被阻塞。

 

43) 如何在Java中创建Immutable对象?

 

44) Java中的ReadWriteLock是什么?

 

45) 多线程中的忙循环是什么?

46)volatile 变量和 atomic 变量有什么不同?

47) 如果同步块内的线程抛出异常会发生什么?

48) 单例模式的双检锁是什么?

49) 如何在Java中创建线程安全的Singleton?

懒汉式:双重检查

饿汉式:私有化构造器、静态方法创建实例

或者使用枚举

51) 如何强制启动一个线程?

 这个问题就像是如何强制进行Java垃圾回收,目前还没有觉得方法,虽然你可以使用System.gc()来进行垃圾回收,但是不保证能成功。

在Java里面没有办法强制启动一个线程,它是被线程调度器控制着且Java没有公布相关的API。

52) Java中的fork join框架是什么?

fork join框架是线程池的另外一种实现,可以将任务不断拆分成小的单元,然后执行,执行结果在合并,使用了

递归的方式。

53) Java多线程中调用wait() 和 sleep()方法有什么不同?

wait和sleep都会放弃cpu的执行权,进入阻塞,wait的线程必须等待notify唤醒,sleep时间到后会

自动进入就绪状态。wait后放弃锁,sleep不会放弃锁。

 

posted @ 2020-03-24 21:43  程序员三藏  阅读(221)  评论(0编辑  收藏  举报