Java高性能编程

Java线程状态详解及常用方法介绍

2019-11-10  本文已影响0人  书中乌鸦不是鸟

                    过硬的技术 + 透彻的金融业务 + 心理学 = 互联网金融专家

写在文章前面的:在之前的Java中级甚至Java的高级开发面试中,一般java的多线程开发就是问问基本问题,但今年随着社会大经济环境的变化,和过剩的开发人员的涌现,所以市场要求也越来越高,多线程也成了必须要重点掌握的知识点。

多线程和多任务往往是使用多处理器系统的最合理方式。因为并发在单处理器上执行是没有意义的,在单处理器上并发和顺序的执行并没有什么本质的区别。

使用多线程的好处就是更好的利用CPU的性能,更好的用户体验等。

一、线程的基本知识

了解线程之前必须要了解进程了,进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。

而线程是进程的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。

二、线程的状态

线程一共有五种状态(等待和超时等待归属于等待):New(新建),Runnable(可运行),Blocked(阻塞状态),Waiting(等待状态 和  Timed Waiting(超时等待)) ,Terminated(终止)

三、常用方法详解

常用方法有:start(),run(),wait(),sleep(),notify(),notifyAll(),join(),yield(),park(),unpark(),join(),synchronized 方法或方法块。

1、start() :启动相应线程,该方法的返回并不代表相应的线程被启动。一个Thread实例的start方法只能够被调用一次,多次调用会导致异常的抛出。

2、run():用于实现线程的任务处理逻辑。该方法是由Java虚拟机直接调用的,一般情况下应用程序不应该调用该方法。

3、wait():让线程等待或者使用wait(3000)的方式将线程阻塞3秒钟,sleep()方法也是可以将线程休眠或者休眠一定时间的,两个方法都可以引起阻塞。

4、notify() 是唤醒线程,API文档:Wakes up a single thread that is waiting on this object's monitor。 NotifyAll() 在API文档中解释为:Wakes up all threads that are waiting on this object's monitor.(欢迎所有线程,可以作用于wait(),当然也可以作用于sleep()的线程)。

notify():唤醒一个处于等待状态的线程,在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

5、park() 和unpark(),unpark函数为线程提供“许可(permit)”,线程调用park函数则等待“许可”。这个有点像信号量,但是这个“许可”是不能叠加的,“许可”是一次性的。比如线程B连续调用了三次unpark函数,当线程A调用park函数就使用掉这个“许可”,如果线程A再次调用park,则进入等待状态。注意,unpark函数可以先于park调用。比如线程B调用unpark函数,给线程A发了一个“许可”,那么当线程A调用park时,它发现已经有“许可”了,那么它会马上再继续运行。

6、join(),该方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。

7、yield(),调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。而且,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

wait()和sleep()的区别是:

     a:wait方法是作用在Object上的,而sleep是作用在线程上的,当调用Thread.sleep时,并不能改变对象的状态。

证据如下:

  b:最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁)。

  c:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围) 

  d:sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常 

sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。

注意:sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。

上一篇下一篇

猜你喜欢

热点阅读