多线程面试题总结

1.进程和线程的区别

根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

2.Callable接口和Runnable接口的区别

(1) Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。

(2) Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

(3) call方法可以抛出异常,run方法不可以。

(4) 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

3.线程六种状态的切换

在这里插入图片描述

4.start()方法的调用和run()方法调用有什么区别?

1.调用start()方法:

通知“线程规划器”当前线程已经准备就绪,等待调用线程对象的run()方法。这个过程就是让系统安排一个时间来调用Thread中的run()方法,使线程得到运行,启动线程,具有异步执行的效果。

调用start()方法,也就是线程状态转变成可运行状态的过程。

2.调用run()方法:

不是异步执行,而是同步执行,当前线程并不交给“线程规划器”来处理,而是由main主线程来调用run()方法,也就是必须等run()方法中的代码执行完后才可以执行后面的代码。

5.总结sleep和yield的区别

  1. sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
  2. sleep()可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;yield()只能使同优先级的线程有执行的机会。

6.isInterrupted和interrupted方法之间的区别

interrupted()是静态方法,它调用的是currentThread().isInterrupted(true)方法,即说明是返回当前线程的是否已经中断的状态值,而且有清理中断状态的机制。而isInterrupted()是一个实例方法,它调用的是isInterrupted(false)方法,意思是返回线程是否已经中断的状态,它没有清理中断状态的机制。

7.守护线程

当有一个无限循环的线程,当其他程序执行完后,他就需要关闭,这时应该设置他为守护线程,设置方法为

Thread t = new MyThread();
t.setDaemon(true);
t.start();

8.并发编程的三大特性

1、原子性
对于成员变量a来说,如果线程A执行以下操作:

a++;

此时需要分三步执行:

(1)读取a的值

(2)将a的值加1

(3)将加1后的值赋给a

在执行以上三步过程中,如果另一个线程B对a进行了操作,那么就不能保证原子性了。

要保证原子性,可以加锁,如synchronized

2、可见性
要理解可见性,需要先理解cpu的高速缓存。高速缓存是cpu的一块儿缓存区。如果线程修改了某个变量的值,那么是先将修改过的值先放入缓存区,然后满足一定条件后才会同步到内存区。同步到内存区后,其他线程才可以看见变量的改变。

可见性是指,当有一个线程修改某个成员变量的值时,其他变量可以立马看到修改过的值。
3、有序性
处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。

9.synchronized同步代码块和同步方法的底层原理

1)每一个对象都与一个monitor相关联,一个monitor lock只能被一个线程在某一时间内获得,
在一个线程尝试获取与对象关联的monitor lock的时候会发生如下事情:

  • a.如果monitor的计数器为0,表示当前monitor lock没有被任何线程锁获取,某个线程获取之后,需要对该计数器进行加一,表示当前的线程是这个monitor的owner
  • b.如果一个已经拥有monitor lock的线程再次想要拥有这个monitor lock,会使得monitor的计数器累加(synchornized是一个可重入锁)
  • c.如果monitor的计数器不为0,被其他线程所拥有,此时该线程尝试获取monitor lock,会被陷入阻塞,直到monitor的计数器再次为0,才能够再次尝试获取monitor的使用权
    2)monitorexit释放对monitor的使用权,将monitor的计数器减为1,如果计数器为0,表示该线程不再拥有monitor的所有权

同步方法 静态常量池中多一个ACC_SYNCHORNIZED标识符,表示当前的方法是同步方法

10.关于synchornzied锁升级的过程

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值