• 线程


    进程和线程

    • 进程

      • 一个应用程序的实例
      • 是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
    • 线程

      • 属于进程中的一个执行单元,线程是通过cpu执行的基本单元
      • 一个进程中至少有一个主线程存在,主线程可以去申请子线程

    cpu执行任务是通过调用进程中的线程
    一台电脑中 同时又很多个进程在运行状态
    这些进程,又同时有很多个线程在运行状态
    单核cpu 同一时间只能调用一个线程

    java中一个main方法一个进程,并且开启一个主线程,每个线程有个ID,在java中线程类是Thread类

    Thread.currentThread()获取当前线程运行实例对象
    Thread.currentThread().getId()获取当前运行的线程ID

    JVM启动时就启动了多个线程,至少有两个线程可以分析的出来

    1. 执行main函数的线程
      • 该线程的任务代码都定义在main函数中
    2. 负责垃圾回收的线程

    线程的状态

    1. 新建状态(New):新创建了一个线程对象。
    2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
    3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
    4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
      (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
      (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
      (三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁)
    5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    创建线程的方法

    在java中开启线程有3种方法:

    1. 继承Thread类
    2. 实现Runnable接口
    3. 线程池(这里暂时先不写了)
    创建线程方式一:继承Thread类
    1. 定义一个类继承Thread类
    2. 覆盖Thead类中的run方法

      为什么要覆盖run方法?

      创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行。
      而运行的制定代码就是这个执行路径的任务,jvm创建的主线程的任务都定义在主函数中

      而自定义的线程它的任务在哪呢?

      Thread类用于描述线程,线程是需要任务的,所以Thread类也对任务的描述。
      这个任务即使通过Thread类中的run方法来体现,也就是说,run方法就是封装自定义线程运行任务的函数

      run方法中定义就是线程要运行的任务代码

      开启线程是为了运行指定代码,所以只有继承Thread类,并覆盖run方法。将运行的代码定义在run方法中即可

    3. 直接创建Thread的子类对象,并启动 object.start();
    大专栏  线程建线程方式二:通过接口的形式完成 Runnable的实现
    1. 定义类实现 implements Runnable
    2. 覆盖接口中的run 方法,将线程的任务代码封装到run方法中
    3. 通过Thread类创建线程对象,并将Runnable接口的子类对象最为Thread类的构造函数的参数进行传递 Thread t1 = new Thread(d);
    4. 调用线程对象的start方法开启线程 t1.start();

    线程中常用方法

    • Thread.yield( )

      • Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。
      • yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
    • synchronized

      • synchronized加在方法前面就是方法锁,作用是保证同一时间只能有一个线程进入该方法执行
      • synchronized作用于对象 就是对象锁
        • 对象锁是实例方法使用synchronized关键字后,如果是多个线程访问同个对象的sychronized块,是同步的,但是访问不同对象的话还是不同步的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    User user = new User();
    synchronized(user){
    while(...){
    ...
    }
    user.notify() 唤醒其中一个等待操作对象(wait)的线程
    user.wait(); //当前线程睡眠 释放对象锁
    //当前线程睡眠,直到被别人用notify或notifyAll唤醒该线程
    }

    Object.wait()当前线程睡眠 释放对象锁
    Object.notify() 随机唤醒其中一个wait的线程
    Object.notifyAll() 唤醒所有wait中的线程
    Thread.sleep(20000); 睡眠

    wait和sleep的区别:
    wait是object类的方法,sleep是Thread类的方法
    2个方法都可以让线程暂停运行
    但是wait会释放对象锁,sleep不会。

    • 中断:
      中断在java中主要有3个方法:interrupt(),sInterrupted()和interrupted()。

      • interrupt(),在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从,由具体的代码实现决定。
      • isInterrupted(),用来判断当前线程的中断状态(true or false)。
      • interrupted()是个Thread的static方法,用来恢复中断状态。
    • Thread. join();

      • join的意思是使得放弃当前线程的执行,并返回对应的线程
      • 例如下面代码的意思就是:
        程序在main线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕
        所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会
    1
    2
    3
    4
    5
    ThreadJoinTest t1 = new ThreadJoinTest("小明");
    ThreadJoinTest t2 = new ThreadJoinTest("小东");
    t1.start();
    t1.join();
    t2.start();

    就这样吧

  • 相关阅读:
    WebMatrix简介与预览
    使用NuGet增加常见包引用
    用Jquery实现的一个Table的帮助js
    使用AspNetPager进行存储过程分页
    Android之旅AppWidget
    SQL积累
    【问题记录】Asp.net WebApplication和WebSite中用户控件的使用区别
    ActionScript 3.0工厂模式实例
    ActionScript 3.0 实现单态模式
    装饰器模式小结
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12366307.html
Copyright © 2020-2023  润新知