线程相关问题

一、试着解释一下线程的生命周期

首先是新建状态,使用new关键字新建线程后,线程就会处于新建状态,此时,如果我们使用start方法将该线程启动后,线程将进入准备状态,准备争抢CPU,一旦抢占到CPU,该线程会自动调用run方法,此时即为运行状态,如果没有抢到CPU或是使用wait()、sleep()等方法将CPU让出去后,该线程将会进入等待状态也叫做阻塞状态、挂起状态等,等待完毕后,会再次进入准备状态,直至运行成功,之后将会进入销毁状态,资源将被释放,我们也可以使用stop方法,手动的进入销毁状态。

 二、sleep()、yield()、join()和wait()方法可以起到哪些作用呢?又有什么区别呢?

它们都能够使线程进入等待状态。

  • Sleep()是Thread类的一个静态方法,它可以让当前正在执行的线程处于睡眠状态,我们需要指定一个睡眠时间,时间过后,线程会自动唤醒,唤醒后,线程会进入就绪状态,重新准备争抢CPU。

需要注意的是,如果该线程抢占了一个对象锁,睡眠期间不会释放对象锁。

  • yield()是一个让步的方法,它会使当前线程让出CPU,与其他线程重新争抢CPU。
  • join(),使用这个方法,我们需要使用其它线程来调用该方法,代表让这个线程插队到自己前面,当指定线程执行完毕后,当前线程才会继续执行。

我们一般使用join()方法用来确保所有的其他线程都执行完毕,当前线程再继续执行。

  • 最后是object.wait(),它是object所有对象都拥有的方法。该方法必须用在同步方法或同步代码段中,因为线程要想执行同步方法或同步代码段,需要先获得对应的锁对象。

在同步方法或同步代码段中,获得的是哪个对象的对象锁,才可以调用哪个对象的wait方法。

它表示让出当前对象的对象锁,获得当前对象锁的当前线程处于等待状态,等待再次获得该对象的对象锁,才能继续执行剩下未完成部分代码。

当其他线程使用完该对象的对象锁后,需要调用该对象的notify或notifyall方法唤醒等因为wait方法而等待该对象锁的线程。

三、synchronized为什么需要锁升级呢?锁升级是一个怎样的过程呢?

早先版本(1.6-) , synchronized属于重量级锁,直接使用系统级别的互斥锁,所以它会存在用户态与内核态的切换,性能较低。所以1.5版本的juc中,lock对于synchronized有所优化1.6 直接对synchronized做了优化提供了锁升级的机制。

接下来使,它的锁升级机制,首先,在最开始的4秒,它是一个无锁状态,四秒过后,他会变成一个偏行所,此时,如果有第一个线程访问,它会对该线程做一个记录,这个线程可以自由通行,此时,如果出现其他线程,它会判断一下线程的数量,如果只有少量线程,他会转成轻量级锁,使用CAS+自选的方式进行处理,如果在偏行锁时,线程数量激增,或是在轻量级锁时,线程数过多或是自选次数过多,它最终也都会转为重量级锁,使用mutex的方式上锁。最后,如果在最开始的四秒内,立刻就有线程访问,他也会转变为轻量级锁。

四、并发工具类中的CountDownLatch类(计数器)和Semaphore类(信号量)有什么作用呢?

这两个类都可以配合线程池使用。

 CountDownLatch类可以提供计数器,当所有的线程都执行完毕后,当前线程再执行。类似于多线程中的join方法。

CountDownLatch latch = new CountDownLatch(5);通过构造方法,可以设置计数器的初值

latch.countDown()方法可以使计数器-1

latch.await();会使当前线程一直处于等待状态,直到计数器为0

Semaphore类,可以提供一组信号量,每一个线程都可以申请信号量, 确保指定数量的线程同时执行。每一个线程执行完毕后,都需要释放信号量

Semaphore s = new Semaphore(5); 通过构造方法,可以设置信号量的初值

s.acquire();使用该方法获取信号量

s.release();使用该方法释放信号量

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值