多线程面试

什么是线程?
线程是操作系统能够进行运算调度最小单位,进程包含线程,是进程的实际运作
单位。可以使用多线程对运算密集型的任务提速,减少时间

**线程和进程的区别?**
线程是进程的子集,一个进程可以包含多个线程,每个线程并行执行不同的任务。
不同的线程使用不同的内存空间,而所有的线程共享一片相同的内存空间。每个线程都
拥有单独的栈内存来存储本地数据。

**如何在Java中实现线程?**
在语言层面有两种方式。Java.lang.Thread类的实例就是一个线程但是它需要
调用Java.lang.Runnable接口来执行,由于线程本身就是调用的Runnable接口你可以继承
Java.lang,Thread类或者直接调用Runnable接口来重写run()方法实现线程。

**用Runnable还是Thread?**
通过继承Thread类或者调用Runnable接口都可以实现线程,那么用那个比教
好呢,在Java中Java不支持类的多重继承,但是允许你调用多个接口,那么还是Runnable好

**Thread类中的start()和run()方法有什么不同?**
start()方法被用来启动新线程的线程,而start()内部调用了run方法,这和直接
调用run方法是不同的,当调用run方法的时候,只会在原来的线程中调用,没有新的线程
启动,start才会调用新的线程。

**Java中的Runnable和callable有什么不同?**
Runnable和callable都是在不同的线程中执行任务,Runnable在jdk1.0开始
就有了,callable是在jdk1.5增加的。他们主要的区别是callable的call方法可以返回值
和异常,而Runnable的run方法没有这些功能,callable可以返回装载有什么结果的future对象。

**Java内存模型是什么?**
Java内存模型规定和指定Java程序在不同的内存架构,cpu和操作系统间有确定性型行为。他在多线程的情况下尤其重要。Java内存建模对一个线程所作的变动能被其他线程可见提供保证,他们之间先发生关系。这个关系定义了一些规则让程序员在并发编程时思路
更清晰。比如先前确保关系:
线程内的代码能够按先后顺序执行,这被称为程序次序规则
对于同一个锁,一个解锁操作一定要发生在时间上后一个锁定操作前,也叫做
管程锁定规则。
前一个对volatile的写操作在后一个volatile的读操作之前,也叫做volatile变量规则
一个线程内的任何操作必须在这个线程的start调用之后,也叫做线程启动规则
一个线程的所有操作都必须在这个线程终止之前,线程终止规则
一个对象的终结操作必须早这个对象构造完成之后,也叫对象终结规则
可传递性

**Java中cyclicBarrier和countDownLatch有什么不同?**
cyclicBarrier和用来让一组线程等待其他线程。与cyclicBarrier不同的是,coundownLatch不能重新使用。

**什么是线程安全?vector是一个线程安全类吗?**
如果你的代码所在的进程中有多个线程在同时进行,而这写线程可能会同时运行这段代码。如果每次运行的结果和单线程运行结果是一样的,而且其他的变量和值也和预期的一样,这就是线程安全。一个线程安全的计数器类的同一实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全的和线程非安全的。vector是同步方法来实现线程安全的,而和他类似的arrayList不是线程安全的。

**Java中什么是静态条件?**
静态条件会导致线程在并发情况下出现一些bug。多线程对一些资源的竞争的时候就会产生静态条件,如果首先要执行的程序竞争失败后排到后面执行了,那么整个程序就会出现一些不确定的bug很难发现而且会重复出现,因为线程间的随机竞争

**Java中如何停止一个线程?**
Java提供了很丰富的api但为什么没有停止线程的api。jdk1.0本来有一些想stop,suspend和resume的控制方法,但是由于潜在线程死锁的威胁,因此在后续的jdk版本中他们也被抛弃了,之后Java api的设计者就没有提供一个兼任线程安全的方法来停止一个线程,让run或者call方法执行完的时候线程会自动结束,如果手动结束可以用volatile 布尔变量来退出run方法的循环或者取消任务来中断线程

**一个线程运行时发生异常会怎样?**
简单的说,如果异常没有被捕获该线程将会停止执行。tread.uncaughtExceptionHandler是用于处理捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候jvm会使用thread.getUnCaughtExceptionHandler()来查询线程的,并将线程和异常作为参数传递给方法进行处理。

**如何在两个线程间进行数据共享?**
可以通过共享对象来实现,或者是使用像阻塞队列这样并发的数据结构

**Java中的notify和notifyAll有什么区别?**
因为多线程可以等待单监控锁,Java API的设计人员提供了一些方法当等待条件改变的时候通知他们,但是这些方法没有完全实现。notify方法不能唤醒某个具体的线程,所有只有一个现在等待的时候才能用notify方法。而notifyAll方法可以唤醒所有的线程并允许他们争夺锁确保了至少有一个线程能继续运行。

**什么是ThreadLocal变量?**
ThreadLocal是Java里的一种特殊的变量。每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量。他是为创建代价高昂的对象获取线程安全的好办法,


**Java中的同步集合和并发集合有什么区别?**
同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。在Java1.5之前程序员们只有同步集合用来在多线程并发的时候会导致争用,阻碍了系统的扩展性。java5介绍了并发集合像concurrentHashMap,不仅提供线程安全还用锁分离和内部分区等现代技术提高可扩展性。

**Java中堆和栈有什么不同?**
栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调试,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果有多个线程使用该变量就可能引发问题,这是volatile变量就可以发挥作用了,他要求线程从主存中读取变量的值。

**什么是线程池?为什么要使用它?**
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,他们被称为
线程池,里面的线程叫做工作线程。从jdk1.5开始,Java API提供了executor框架让你可以创建不同的线程池。
比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池

**如何避免死锁?**
死锁是值两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外来
作用,他们都将无法进行下去。因为死锁会让你的程序挂起无法执行任务,死锁的发生必须满足以下四个条件:
1)互斥条件:一个资源每次只能被一个进程使用
2)请求与保持条件:一个进程因请求资源而阻塞时,以获得的资源保持不妨
3)不剥夺条件:进程以获得的资源,在为使用完成之前,不能强行剥夺。
4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
避免死锁最简单的方法就是阻止循环等待条件,将系统中的所有资源设置标志位,排序,规定所有的进程申请资源
必须以一定的顺序来操作避免死锁。

**有三个线程T1,T2,T3怎么确保他们按顺序执行?**
可以用线程类的join方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个
线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。

**Java多线程中调用wait()和sleep()方法有什么不同?**
Java程序中wait和sleep都会造成某种形式的暂停,他们可以满足不同的需求。wait()方法用于线程间通信,
如果等待条件为真且其他线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值