多线程相关面试题及其解答

Q:什么是线程?什么是进程?线程和进程有什么区别?

A:线程:又称“轻量级进程”,是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。

进程: 系统进行资源分配和调度的基本单位。

两者之间的区别:
地址空间和其他资源:进程间相互独立,同一进程的各线程间共享,某进程中的线程在其他进程不可见。
通信:进程间通信 IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
调度和切换:线程上下文切换比进程上下文切换要快得多。
在多线程 OS 中,进程不是一个可执行的实体。


Q:多线程编程的好处是什么?

A:发挥多核 CPU 的优势(提高性能)、防止阻塞、便于建模


Q:有几种创建线程的方式?哪种比较好?

A:①、实现 Runnable 接口(较好:灵活,减少耦合度);②、继承 Thread 类。


Q:Runnable 接口和 Callable 接口的区别?

A:Callable 接口中的 call() 方法是可以返回值和抛出异常,是一个泛型,和 Future / FutureTask 配合来获取结果。而 Runnalbe 接口的 run() 方法,无返回值。


Q:Java 中 CyclicBarrier 和 CountDownLatch 有什么不同?

A:①、CyclicBarrier 是 n 个线程,相互等待;CountDownLatch 是一个或多个线程,等待另外 n 个线程执行完,再执行。
②、CyclicBarrier 计数;CountDownLatch 计数。
③、CyclicBarrier 计数达到指定值时,计数置为 0 重新开始;CountDownLatch 计数为 0 时,无法重置。(不可重复利用
④、CyclicBarrier 调用 await() 方法计数加 1 , 若加 1 后的值不等于构造方法的值,则线程阻塞;CountDownLatch 调用 countDown() 方法计数减 1 ,调用 await() 方法只进行阻塞,对计数没任何影响。


Q:volatile 是什么?作用是什么?

A:volatile 是一个类型修饰符,是用来修饰被不同线程访问和修改的变量

主要作用有两个:①、内存可见性,即线程 A 对 volatile 变量的修改,其他线程获取的 volatile 变量都是最新的;②、可以禁止指令(程序执行的顺序)重排序


Q:什么是线程安全?

A:线程安全:多线程访问时,采用了加锁机制,当一个数据访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全不提供数据访问保护,有可能多个线程先后更改数据造成所得到的数据是脏数据


Q:线程安全分为哪几种级别?

A:①、不可变不变的对象绝对是线程安全的,不需要线程同步,如 String、Long、BigInteger;
②、无条件的线程安全:对象自身做了足够多的内部同步,也不需要外部同步,如 Random、ConcurrentHahsMap、Concurrent 集合、atomic;
③、有条件的线程安全:对象的部分方法可以无条件安全使用,但是有些地方需要外部同步,需要 Collectiongs.synchronized;有条件线程安全的最常见的例子是遍历由 HashTable 或者 Vector 或者返回的迭代器;
④、非线程安全(线程兼容):对象本身不提供线程安全机制,但是通过外部同步,可以在并发环境使用,如 ArrayList、HashMap;
⑤、线程对立:即使外部进行了同步调用,也不能保证线程安全,这种情况非常少,如 System.setOut()、System.runFinalizersOnExit()。


Q:如何正确地停止一个线程?

A:①、使用退出标志,使线程正常退出,也就是当 run 方法完成后线程终止;
②、使用 interrupt 方法中断线程
③、使用 stop 方法强行终止,但是不推荐使用,因为 stop 和 suspend 以及 resume 一样存在死锁威胁,并且都是过期作废的方法。


Q:一个线程运行时发生异常会怎样?

A:①、如果异常没有被捕获,该线程将会停止执行
②、如果这个线程持有某个对象的监视器,那么这个对象监视器会被立即释放


Q:两个线程之间,如何实现数据共享?

A:①、使用同一个 Runnable 对象;
②、使用不同的 Runnable 对象:
i、将共享数据分别传递给两个不同的线程
ii、将这些 Runnable 对象作为一个内部类,将共享数据作为成员变量


Q:sleep() 方法和 wait() 方法有什么区别?

A:①、所在的类:sleep 在 Thread 类中、wait 在 Object 类中;
②、锁:sleep 方法没有释放锁、wait 方法释放了锁
③、使用范围:sleep 可以在任何地方使用、而 wait,notify 和 notifyAll 只能在同步控制方法或者同步控制块里面使用


Q:ThreadLoacl 是什么?作用是什么?

A:它是线程局部变量,每个线程都有自己的 ThreadLocal。

作用:把数据进行隔离,数据不共享(空间换时间,在 Thread 中维护了一个以开地址法实现的 ThreadLocalMap )。


Q:为什么 wait() 方法和 notify()/notifyAll() 方法要在同步块( synchronized )中被调用?

A:JDK 强制的,方法调用之前必须先获得对象的锁。如果不这样做,就会抛出 IllegalMonitorStateException 异常。


Q:同步集合 & 并发集合的区别?

A:都支持线程安全,主要区别体现在性能可扩展性

性能:同步集合会把整个 Map 或者 List 锁起来,而并发集合不会。所以同步集合比并发集合慢的多。
可扩展性并发集合不仅提供线程安全,还用锁分离和内部分区等现代技术来提高可扩展性。


Q:什么是线程池? 为什么要使用它?

A:在程序启动时,就创建若干个线程来响应请求。使用它,可以避免频繁地创建和销毁线程,达到线程对象的重用,还可以根据项目灵活地控制并发的数目


Q:什么是死锁?死锁发生的必要条件?如何避免死锁?

A:死锁:两个及以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们都将无法推进下去。

死锁的必要条件
①、互斥条件:一个资源每次只能被一个进程使用;
②、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不变;
③、不剥夺条件:进程已获得的资源,在未使用之前,不能强行剥夺;
④、循环等待条件:若干进程之间形成一种头尾相连的循环等待资源关系。

避免死锁最简单的方法阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序做操作。


Q:活锁 & 死锁的区别?

A:活锁进程的状态可以改变但是却不能继续执行


Q:怎么检测一个线程是否拥有锁?

A:Thread 中的 holdsLock() 方法:如果当且仅当当前线程拥有某个具体对象的锁时,返回 true


Q:synchronized & ReentrantLock 的区别?

A:两者都是加锁方式同步(阻塞式同步)

其本质上的区别:synchronized 是关键字,ReentrantLock 是类。
相对于 synchronized 而言,ReentrantLock 类提供了一些高级功能:
①、等待可中断:持有锁的线程长期不释放时,正在等待的线程可以选择放弃等待,这相等于 synchronized 来说,避免了死锁
②、公平锁:synchronized 只能是非公平锁,ReenTrantLock 可以通过构造函数的参数来指定公平锁和非公平锁。(公平锁:先等待的线程先得到锁);
③、锁绑定多个条件:一个 ReentrantLock 对象可以同时绑定多个对象。
④、锁机制不一样:synchronized


Q:如何保证线程按照指定顺序执行?

A:使用 new Thread().join() 方法:等待线程结束。也就是说通过一个线程等待另一个线程执行完毕,再继续执行,来实现。


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

A:当一个任务不能被调度执行时,ThreadPoolExecutor 的 submit() 方法将会抛出 RejectedExecutionException 异常。


Q:Java 线程池中 submit() & execute() 方法有什么区别?

A:①、接收的参数不一样;②、submit() 有返回值,execute() 没有
;③、submit() 方便 Exception 处理


Q:ReadWriteLock 是什么?

A:维护一对关联的锁,一个用于只读操作,一个用于写操作读锁是共享的,而写锁是独占的。


Q:多线程中的忙循环是什么?使用它的目的是什么?

A:忙循环:用循环让一个线程等待,不会放弃 CPU

目的:为了保留 CPU 缓存,避免重建缓存和减少等待重建时间。在多核系统中,一个等待线程醒来时,可能会在另一个内核运行,这样就会重建缓存。


Q:遵循的多线程的最佳实践有哪几条?

A:①、给线程起一个有意义的名字;②、避免锁定和缩小同步的范围;③、多用同步类,少用 wait 和 notify;④、多用并发集合,少用同步集合。


Q:如何强制启动一个线程?

A:它是被线程调度器控制的,并且 Java 没有公布相关的 API。


Q:fork-join 框架是什么?

A:Java7 提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。使用了工作窃取算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值