• Java并发编程系列(一)基础概念


    1.线程状态图:

     5种状态:

    1.新建(new)

    2.就绪(Runnable)

    3.运行(Running)

    4.阻塞(Blocked)

    • 等待阻塞:调用了wait()方法

    • 同步阻塞:调用了synchronized()方法或执行了synchronized代码块,但是没有获取到对象的同步锁。

    • 其他阻塞:调用sleep()或join()方法

    5.死亡(Dead)

    相关方法:

    1.run():

    是Runnable接口里唯一的一个抽象方法,可以被重复调用。直接调用run方法,并不会启动新线程,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到多线程的目的。总结:run方法只是thread的一个普通方法调用,还是在主线程里执行。

    
    

    2.start():

    启动一个新线程。通过start()方法来启动的新线程,使线程处于就绪(可运行)状态,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。start()不能被重复调用。用start方法来启动线程,真正实现了多线程运行,即无需等待某个线程的run方法体代码执行完毕就直接继续执行下面的代码。

    3.start()和run()的区别:

    特性 start() run()
    启动一个新线程 不能
    重复调用 不能
    是否实现多线程

    4.wait()/notify()/notifyAll()

    这三个都是Object()类的方法:

    wait():让当前线程处于“等待(阻塞,挂起)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。

    notify():唤醒在此对象监视器上等待的单个线程。

    notifyAll():唤醒在此对象监视器上等待的所有线程。

    Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。

    wait()会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!
    OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?或者说,wait()等待线程和notify()之间是通过什么关联起来的?答案是:依据“对象的同步锁”。

    负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。

    总之,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。

    5.yield():

    yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

    yield()和wait()的区别:

    wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而不yield()是让线程由“运行状态”进入到“就绪状态”。
    wait()是会线程释放它所持有对象的同步锁,而yield()方法不会释放锁。

    6.sleep():

    sleep() 定义在Thread.java中。
    sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。

    sleep()和wait()的区别:

     wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”,同时也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
    但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。

    7.join():

    join()使一个子线程加入一个主线程,并且让“主线程”等待“子线程”结束之后才能继续运行。

    8.interrupt():中断一个线程

     

     2.synchronized关键字的用法

    第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
    第二条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块
    第三条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

    主要分为:

    1.synchronized方法

    2.synchronized块:synchronized(this):获取当前对象的同步锁/synchronized(obj):获取某一个特定对象的对象锁

  • 相关阅读:
    关于Mysql几周的整理文档
    压力开关
    【团队】汇总
    2017级面向对象程序设计——团队作业1
    东风吹十里,风华一笔得。
    【团队】实验品
    【2017级面向对象程序设计】作业四
    【C#】C#学习笔记_1
    【2017级面向对象程序设计】作业三
    【2017级面向对象程序设计】作业二
  • 原文地址:https://www.cnblogs.com/umrx/p/8011999.html
Copyright © 2020-2023  润新知