首页 > 编程语言 >Java SE 宋红康 days02-高级篇-多线程

Java SE 宋红康 days02-高级篇-多线程

时间:2022-09-30 22:34:55浏览次数:66  
标签:同步 Java Thread 创建 线程 days02 多线程 方法 wait

1. 进程和线程

  进程

    是程序的一次执行过程,或是正在运行的一个程序;是动态的过程,有它自身的产生、存在和消亡的过程(生命周期)

    进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域

  线程(是一个程序内部的一条执行路径)

    若一个进程同一时间并行执行多个线程,就是支持多线程的;

    线程作为调度和执行的单位,每个线程拥有独立的运行栈程序计数器(pc),线程切换的开销小

    一个进程中的多个线程共享相同的内存单元/内存地址空间,从同一堆中分配对象,可以访问相同的变量和对象

2. 创建线程

  方法4使用线程池(经常创建销毁使用量特别大的资源,比如并发情况下的线程,对性能影响很大)

    思路提前创建好多个线程,放入线程池中,使用时直接获取,使用完后放回线程池中,可以避免频繁创建销毁,实现重复利用;

    好处

      提高响应速度:减少创建新线程的时间

      降低资源消耗:重复利用线程池中线程,不需要每次创建

      便于线程管理:corePoolSize(核心池的大小)、maximumPoolSize(最大线程数)、keepAliveTime(线程没有任务时最多保持多久会终止);

    

 

     步骤:

      a. 提供指定线程数量的线程池(可以在之后设置线程池属性)

      b. 执行指定的线程操作,需要提供实现 Runnable 接口或 Callable 接口实现类的对象

      c. 关闭连接池


  方法1:

    a. 创建一个继承于 Thread 类的子类

    b. 重写 Thread 类的 run()方法

    c. 创建 Thread 类的子类对象

    d. 通过此对象调用 start()

      ① 启动当前线程

      ② 调用当前线程的 run()


  方法2:

    a. 创建一个实现了 Runnable 接口

    b. 实现类去实现 Runnable 接口的类

    c. 创建实现类的对象

    d. 将此对象作为参数传递到 Thread 类的构造器中,创建 Thread 类的对象

    e. 通过 Thread 类的对象调用 start()


  方法1和2的对比:(优先选择 Runnable 接口,原因如下)

    a. 实现的方式没有类的单继承性的局限性

    b. 实现的方式更适合来处理多个线程有共享数据的情况

    联系:两种都需要重写 run();将线程要执行的逻辑声明在 run()中;


  新增方法3:使用 Callable 接口

    a. 创建一个实现 Callable 类的实现类

    b. 实现 call 方法,将此线程需要执行的操作声明在 call 中

    c. 创建 Callable 接口实现类对象

    d. 将此 Callable 接口实现类的对象作为传递到 FutureTask 构造器中,创建 FutureTask 的对象

    e. 将 FutureTask 的对象作为参数传递到 Thread 类的构造器中,创建 Thread 对象,并调用 start();

    f.  FutureTask 对象的 get() 方法获取 Callable 中 call 方法的返回值;

    较之Runnable接口优势在于:可以有返回值、方法可以抛出异常、支持泛型返回值、需要借助FutureTask类(比如获取返回结果);

    Future 接口

      a. 可以对具体 Runnable、Callable 任务的执行结果进行取消、查询是否完成、获取结果等

      b. FutureTask 是 Future 接口的唯一实现类

      c. FutureTask同时实现Runnable、Future接口,既可以作为Runnable被线程执行,又可以作为Future得到Callable返回值;

3. 常用的 Thread 方法

  yield():释放当前cpu的执行权

  join():在线程A中调用线程B的join(),此时线程A就进入阻塞状态,直到线程B完全执行完以后,线程A才结束阻塞;

4. 线程的调度

  同优先级线程组成先进先出队列,使用时间片策略(等时间轮流);

  高优先级优先调度的抢占式策略(高优先级线程抢占CPU);

5. 线程的优先级

  MAX_PRIORITY:10、MIN_PRIORITY:0、NORM_PRIORITY:5

  高优先级优先调度,不意味着低优先级不能调度,只是被调度到的概率低

6. 线程的生命周期

  Thread.State 类定义了线程的状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED)

  重新分为5种:

    新建:Thread类或其子类对象被声明并创建时;

    就绪:新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时已具备运行条件只是没有分配到资源;

    运行:就绪的线程被调度并获得CPU资源,进入运行状态,run()方法定义线程操作及功能;

    阻塞:某种特殊情况下,线程被认为挂起执行输入输出操作让出CPU并临时终止自己执行,进入阻塞;

    死亡:线程完成全部工作被提前强制性终止出现异常

7. 在 Java 中通过同步机制来解决线程的安全问题:

  方式一:同步代码块

    synchronized(同步监视器) {  //需要被同步的代码  }

    说明:

      a. 操作共享数据的代码,即为需要被同步的代码

      b. 共享数据:多个线程共同操作的变量

      c. 同步监视器:锁;任何一个类的对象都可以充当锁(要求多个线程必须要公用一把锁)

    解决了线程的安全问题,但是操作同步代码时只有一个线程参与,其他线程等待,相当于单线程,效率低;

  方式二:同步方法(如果操作共享数据的代码完整的声明在一个方法中,不妨声明此方法是同步的)

    说明:

      a. 同步方法仍然涉及到同步监视器,只是不需要我们显示的声明;

      b. 非静态的同步方法,同步监视器是 this;

       静态的同步方法,同步监视器是当前类本身;

  方式三:Lock锁

    Lock锁: ReentrantLock类(实现了类Lock,拥有与synchronized相同的并发性和内存语义,可以显式加锁、释放锁)

    说明:

      a. 实例化 ReentrantLock类

      b. 给共享数据加锁:Lock()

      c. 给共享数据解锁:unLock()

8. synchronized 与 Lock 

  异同(使用Lock锁,JVM将花费少量时间来调度线程,性能更好,具有更好的扩展性(提供更多子类))

    同:都可以解决线程安全问题

    异:synchronized 机制在执行完相应的同步代码以后自动释放同步监视器

      Lock 需要手动的启动同步(Lock())结束也需要手动实现(unlock())

  使用优先顺序:Lock -> 同步代码块(已经进入方法体,分配了相应资源)-> 同步方法(在方法体外)

9. 线程的通信

  涉及到的三个方法:

    wait():一旦执行,当前线程进入阻塞状态,并释放同步监视器;

    notify():一旦执行,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级最高的那个

    notifyAll():一旦执行,唤醒所有线程

  说明:

    a. wait()、notify()、notifyAll() 必须使用在同步方法或同步代码块中;

    b. wait()、notify()、notifyAll() 方法的调用者必须是同步代码块或同步方法中的同步监视器

    c. wait()、notify()、notifyAll() 是定义在 Object 类中

10. waitsleep 的异同

  同:执行方法都可以是当前线程进入阻塞

  异:1)两个方法声明的位置不同:Thread 类中声明 sleep(),Object 类中声明 wait();

    2)调用的要求不同:sleep() 可以在任何需要的场景下调用,wait() 必须使用在同步代码块或同步方法中;

    3)是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会;

 

标签:同步,Java,Thread,创建,线程,days02,多线程,方法,wait
From: https://www.cnblogs.com/LinxhzZ/p/16746361.html

相关文章

  • java流程控制Scanner的学习
    java包机制为了更好地组织类,java提供了包机制,用于区别类名和命名空间。包语法的格式为:packagepkg1[.pkg2[.pkg3...]]一般公司域名倒置作为包名为了能够使用......
  • Java基础之变量
    Java基础之变量目录Java基础之变量1.变量概述1.1为什么需要变量1.2简单理解1.3变量使用注意事项1.4程序中+号的使用1.5Java数据类型1.6整数类型1.6.1基本介绍1.6.2......
  • JavaSE基础
    1.Java语言跨平台原理平台指的是不同类型的操作系统。Java语言可以跨平台是因为Java语言使用Java虚拟机屏蔽了具体的操作系统信息,不同的操作系统对应着不同的Java虚拟机......
  • JAVA 内部类
    一、内部静态类:1.访问内部静态类时,不需要实例化外部类。publicclassOuter{staticclassInner{}}classOtherClass{Outer.Inneroi=newOu......
  • Java笔记1
    一、CMD1、win+R,cmd2、常用命令(1)盘+冒号(2)dir显示内容(3)cd文件名(进入)(4)cd..(返回)(5)cd\(回家)(6)cls清屏3、把路径保存到环境变量即可直接访问 二、基本语法1、输......
  • Java笔记2
    静态变量类型说明符是static。静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存......
  • Java实现6种常见排序
    1.冒泡排序(BubbleSort)第0轮3141592653589第1轮1314526535899第2轮1134255356899第3轮11324535568......
  • java多线性--线程创建
    java多线性--线程创建什么是多线程:不同的功能同时进行Process(进程)与Thread(线程)进程是执行程序的一次执行过程,是一个动态的概念。是系统分配资源的单位。一个进程分为......
  • java字符串输入然后语音输出
    1.将jacob.jar考到项目中进行构建路径。2.将jacob-1.17-M2-x32.dll或者jacob-1.17-M2-x64.dll,考到系统盘:\Windows\System32\下面。3.将jacob-1.17-M2-x32.dll或者jacob-......
  • java 前后端开发模式简单说明
    实际上我以前写过一个简单的web前后端部署模式的说明,以下简单说明下关于java语言的,毕竟这个使用人群比较多参考图前后端彻底分离模式(都独立部署)  web使用基于......