zoukankan      html  css  js  c++  java
  • java多线程

    目标:

      刚学习java的时候学了多线程,刚开始工作的时候很久没有使用到线程的知识,最近有个需求要用到线程,再次回顾一下,顺便学点深一点的线程知识。

     一:什么是线程

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

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

      java给多线程提供了内置的支持,一条线程指的是进程中单一顺序的控制流。一个进程中可以并发多个线程,每个线程中可以并行执行不同的任务。

      多线程是多任务的一种特别形式,但多线程使用了更小的资源开销。多线程能满足程序员编写高效率的程序来达到充分利用CPU的目的。

    二:线程的生命周期

     1、线程的生命周期

      java中线程的生命周期有 新建-->就绪-->运行-->阻塞-->死亡

      新建:线程对象创建后进入新建状态

      就绪:调用start() 方法后 进入就绪状态,就绪状态说明当前线程已经做好了准备随时接受CPU的调度。就绪状态是线程进入运行状态的唯一入口。

      运行:run方法运行,当CPU开始调度处于就绪状态的线程时,此时线程处于得以执行进入运行状态;

      阻塞:处于运行状态的线程暂时放弃对CPU的使用权,停止执行进入到阻塞状态,进入到阻塞状态的线程直到其重新进入就绪状态才可以有机会被CPU重新调度,然后进入到运行状态

          根据阻塞产生的原因不同,阻塞状态又分为三种:

          1)等待阻塞:运行状态中的线程执行wait()方法,使得线程金进入阻塞状态。

          2)同步阻塞:线程再获取synchronized同步锁失敗時,因为synchronized被其他线程锁占用,该线程就会进入到同步阻塞状态;

          3)其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

      死亡:线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

       2、阻塞状态各种方法的区别

      上面我们说让线程处于阻塞状态有各种原因:主要有以下方法 wait(),sleep(long millis) ,join()等,他们之间有什么区别呢?对于这个我一直是N脸懵逼,查阅各种资料后得出以下总结;

      1) wait(),wait()通常和notify()或notifyAll()方法一起使用,他们是Object类的方法,主要用于协调多个线程对共享数据的读取。所以一般是在synchronized同步代码块中使用,也就是说调用wait(),notify()的任务在调用这些方法前必须持有对象的锁(意思就是必须是在同步快代码中,并且该对象拥有CPU控制权处于运行状态才能调用wati()方法)。处于wait()的线程必须用notify来唤醒。wait()会放弃锁标志,让其他线程得到执行机会,notify()唤醒后重新得到执行机会,执行notify后面的代码

      2)sleep(long millis)  sleep()是Thread类的方法,有入参为等待时间,作用是让当前正在执行的线程在指定时间内暂停执行,进入阻塞状态.sleep可以让其他线程得到执行的机会。但是sleep()如果用在synchronized同步快中,其他线程仍然不能访问共享数据,因为该方法不会释放“锁标志”。

      3)join()  是使当前线程内,其他线程对象调用join方法,其他线程执行结束后当前线程才继续执行;

        比如有A、B两个线程,在A线程内 调用B.join()意思就是,A线程先不执行,等待B线程执行结束后在继续执行当前线程。

    1.wait()方法执行后,当前线程立即进入到等待阻塞状态,其后面的代码不会执行;
    
    2.notify()/notifyAll()方法执行后,将唤醒此同步锁对象上的(任意一个-notify()/所有-notifyAll())线程对象,但是,此时还并没有释放同步锁对象,也就是说,如果notify()/notifyAll()后面还有代码,还会继续进行,知道当前线程执行完毕才会释放同步锁对象;
    
    3.notify()/notifyAll()执行后,如果右面有sleep()方法,则会使当前线程进入到阻塞状态,但是同步对象锁没有释放,依然自己保留,那么一定时候后还是会继续执行此线程,接下来同2;
    4.wait() 方法时在那个线程中调用哪个线程进入等待状态,并不是哪个对象,详情见线程中的wait() 与 锁的关系
  • 相关阅读:
    Java分布式锁
    深度神经网络学习过程中的梯度消失问题
    深度神经网络学习过程中的梯度消失问题
    .net下 本地锁、redis分布式锁、zk分布式锁的实现
    .net下 本地锁、redis分布式锁、zk分布式锁的实现
    CLR共享程序集和强命名程序集
    CLR共享程序集和强命名程序集
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 接线过程
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 接线过程
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 安装过程
  • 原文地址:https://www.cnblogs.com/yueguanguanyun/p/9896997.html
Copyright © 2011-2022 走看看