Java-Java基础学习(4)-多线程(2)

3.7. Lambda表达式

  1. 为什么要使用lambda表达式

    • 避免匿名内部类定义过多;
    • 可以让代码看起来更简洁;
    • 去掉一堆没有意义的代码,只留下核心逻辑
  2. 属于函数式编程的概念,格式

    • (params) -> expression [表达式]
    • (params) -> statement [语句]
    • (params) -> {statements}
  3. 函数式接口

    • 任何接口,只有唯一一个抽象方法,就是一个函数式接口
    • 对于函数式接口,可以通过Lambda表达式来创建该接口的对象
  4. 测试

    TestLambda.javapackage com.hzs.basic.multithread;/*** @author Cherist Huan* @version 1.0*/
    public class TestLambda {// 2、静态内部类static  class Like2 implements Ilike{@Overridepublic void lambda() {System.out.println("Like-->2");}}public static void main(String[] args) {Ilike like = null;// 1、外部实现类1like = new Like();like.lambda();// 2、静态内部类like = new Like2();like.lambda();//3、局部内部类class Like3 implements Ilike{@Overridepublic void lambda() {System.out.println("Like-->3");}}like = new Like3();like.lambda();//4、匿名内部类,没有类的名称,必须借助接口或父类like = new Ilike() {@Overridepublic void lambda() {System.out.println("Like-->4");}};like.lambda();//5、用Lambda表达式like = ()->{System.out.println("Like-->5");};like.lambda();}
    }// 1、定义一个函数式接口
    interface Ilike{void lambda();
    }// 2、外部实现类1class Like implements Ilike{@Overridepublic void lambda() {System.out.println("Like-->1");}
    }
  5. a

3.8. 线程的状态(5种)

在这里插入图片描述

线程工包括5中状态:

  • 新建状态(New):线程对象被创建后,就进入了新建状态。例如:,Thread thread = new Thread().

  • 就绪状态(Runnable):也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如:thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。

  • 运行状态(Running):线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态

  • 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

    阻塞的情况分3种:

    • 等待阻塞:通过调用线程的wait()方法,让线程等待某工作的完成;
    • 同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程所占用),它会进入同步阻塞状态;
    • 其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
  • 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

3.9.线程同步

  • 同步方法

    • synchronized关键字,它包括synchronized方法和synchronized块

      同步方法: public synchronized void method(int args){}
      
    • synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,指导该方法返回是释放锁,后面被阻塞的线程才能获得这个锁,继续执行。

    • 缺陷:若将一个大的方法声明为synchronized将会影响效率

  • 同步块

    • 同步块:synchronized (Obj){}

    • Obj称之为同步监视器

      • Obj可以是任何对象,但是推荐使用共享资源作为同步监视器
      • 同步方法中无需指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,或者是class(反射);
    • 同步监视器的执行过程:

      • 1.第一个线程访问,锁定同步监视器,执行其中代码;
      • 2.第二个线程访问,发现同步监视器被锁定,无法访问;
      • 3.第一个线程访问完毕,解锁同步监视器;
      • 4.第二个线程访问,发现同步监视器没有锁,然后锁定并访问。
    • 锁Obj例子

      UnsafeList.java
      package com.hzs.basic.multithread;
      import java.util.ArrayList;
      import java.util.List;/*** @author Cherist Huan* @version 1.0*/
      public class UnsafeList {public static void  main(String[] args)  {List<String> list = new ArrayList<String>();for (int i = 0; i < 10000; i++) {new  Thread(()->{synchronized  (list){list.add(Thread.currentThread().getName());}}).start();}// 获取线程数目boolean flag = true;while(flag){if(Thread.activeCount() <= 2){flag = false;System.out.println(list.size());}}}
      }

3.10.死锁

产生死锁的4个必要条件:

  • 互斥条件:一个资源每次只能被一个进程使用;
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
  • 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺;
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

避免死锁,只要破坏上面至少一个条件即可。

3.11.Lock锁

  • 格式

    class A{private  final   ReentrantLock lock  = new ReentrantLock();public void method(){lock.lock();try{//保证线程安全的代码}finally{lock.unlock();}} 
    }
    
  • 例子

    package com.hzs.basic.multithread;
    import java.util.concurrent.locks.ReentrantLock;
    /*** @author Cherist Huan* @version 1.0*/
    public class TestLock {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(ticket).start();new Thread(ticket).start();new Thread(ticket).start();}
    }class Ticket implements Runnable{private  int ticketNum = 10;private  final   ReentrantLock reentrantLock  = new ReentrantLock();@Overridepublic void run() {while(true) {// 加锁reentrantLock.lock();try {if(ticketNum > 0){Thread.sleep(100);System.out.println(ticketNum--);}else{break;}} catch (InterruptedException e) {e.printStackTrace();} finally {reentrantLock.unlock();}}}
    }
  • synchronized与Lock的对比

    • Lock是显示锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放;

    • Lock只有代码块锁,synchronized有代码块锁和方法锁;

    • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(有很多子类,例如:可重入锁 ReentrantLock);

    • 优先使用顺序:

      Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步方法(方法体之外)

3.12.线程通信

  1. Java提供了几个方法解决线程之间的通信问题
    • wait():表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁;
    • wait(long timeout):指定等待的毫秒数;
    • notify():唤醒一个处于等待状态的线程;
    • notifyAll():唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度。
    • 注意:这些均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException

2. 等待唤醒机制:这是多个线程间的一种协作机制。

  • 谈到线程我们经常想到的是线程间的竞争(race),比如去争夺锁,但这并不是故事的全部,线程间也会有协作机制。

  • 在一个线程满足某个条件时,就进入等待状态(wait() / wait(time)), 等待其他线程执行完他们的指定代码过后再将其唤醒(notify());

  • 或可以指定wait的时间,等时间到了自动唤醒;

  • 在有多个线程进行等待时,如果需要,可以使用 notifyAll()来唤醒所有的等待线程。wait/notify 就是线程间的一种协作机制。

  1. 解决方式
  • 方式一:并发协作模型“生产者/消费者模式”-------->管程法,采用数据缓冲区
  • 方式二:并发协作模型“生产者/消费者模式”-------->信号灯法
  1. 为什么要处理线程间的通信
  • 当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些通信机制,可以协调它们的工作,以此实现多线程共同操作一份数据。(在同步的基础之上解决通信的问题)

  • 比如:线程A用来生产包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消费,此时B线程必须等到A线程完成后才能执行,那么线程A与线程B之间就需要线程通信,即—— 等待唤醒机制。

3.13.线程池

  1. 例子

    package com.hzs.basic.multithread;import java.util.concurrent.Executor;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;/*** @author Cherist Huan* @version 1.0* @note 线程池的使用*/
    public class TestThreadPool {public static void main(String[] args) {// 1、创建ExecutorService executorService = Executors.newFixedThreadPool(10);// 2、执行executorService.execute(new MyThread());executorService.execute(new MyThread());executorService.execute(new MyThread());// 3、关闭executorService.shutdown();}
    }class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
    }
    输出:
    pool-1-thread-2
    pool-1-thread-1
    pool-1-thread-3
    

2、线程池工作原理图

在这里插入图片描述

3、线程池执行流程

  1. 判断核心线程数
  2. 判断任务能否加入到任务队列
  3. 判断最大线程数量
  4. 根据线程池的饱和策略除了任务(是否丢弃任务)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】存储过程、存储函数、触发器

目录 存储过程介绍技术背景存储过程的作用与优势存储过程跟自定义函数很像。它们的区别是&#xff1a; 存储过程的缺点存储过程的特性基本存储过程使用1.创建语法语法说明&#xff1a;使用案例1.创建获取新闻类别数量的存储过程2.创建获取指定新闻类别ID下新闻数量的存储过程 2…

2022年第13届蓝桥杯Java省赛B组-星期计算

一、题目 星期计算 【问题描述】 已知今天是星期六&#xff0c;请问 天后是星期几&#xff1f;注意用数字 1 到 7 表示星期一到星期日。 【答案提交】 这是一道结果填空的题&#xff0c;你只需要算出结果后提交即可。本题的结果为一个整数&#xff0c;在提交答案时只填写这个…

学习人工智能:Attention Is All You Need-1-介绍;Transformer模型架构;编码器,解码器

Transformer模型是目前最成功的chatGPT&#xff0c;Sora&#xff0c;文心一言&#xff0c;LLama&#xff0c;Grok的基础模型。 《Attention Is All You Need》是一篇由Google DeepMind团队在2017年发表的论文&#xff0c;该论文提出了一种新的神经网络模型&#xff0c;即Trans…

极兔速递邀您参观2024长三角快递物流供应链与技术装备展览会

2024长三角快递物流供应链与技术装备展览会&#xff08;杭州&#xff09; 2024年7月8-10日 | 杭州国际博览中心 参展企业介绍 J&T极兔速递是一家全球综合物流服务运营商&#xff0c;快递业务在全球规模最大及增长最快的东南亚和中国市场处于领先地位。公司创立于2015年&a…

部署静态网页②

前言&#xff1a; 前两天写了篇部署个人静态网页的文章&#xff1a;建立部署个人静态网站&#xff0c;有朋友指出了很多问题&#xff0c;然后这篇文章的目的主要是说一下ssl证书的申请&#xff0c;还有推荐介绍另一种部署的方式&#xff0c;还有解决在edge打开域名被警告的情况…

【绘•分享】翻翻书里寻智慧:小布去动物园

part 1 《小布去动物园》是英国著名童书作家罗德坎贝尔创作&#xff0c;收录于广受欢迎的“小布启蒙成长翻翻书”系列。这本书以幼儿为阅读对象&#xff0c;精心设计以促进孩子全面成长。它不仅是一本视觉欣赏的书&#xff0c;更是一本触摸感知书&#xff0c;带领孩子们探索…

实时移动物体检测项目实战代码

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 正文开始&#xff01; 实时…

Linux: 线程安全

Linux 线程共享了进程的资源(地址空间, 页表等), 多个线程同时访问同一个资源就可能产生问题:数据竞争 临界资源: 多个线程共享的资源临界区: 访问临界资源的区域互斥: 任何时刻, 只有一个执行流能进入临界区同步: 以一定顺序访问临界资源原子性: 要么完成, 玩么未完成 锁 死…

什么快递可以寄摩托车?看你要啥样的了

一辆49cc的二冲程摩托车仅需561元。 购买125的组装车不会超过1元&#xff0c;购买250品牌发动机的组装车不会超过4000元。 购买一辆名牌摩托车大约需要4000到10000元。 花一万到两百万多就能买到一辆像样、动力强劲、能玩的炫酷摩托车。 哈哈&#xff0c;就看你想要什么了&…

20240309web前端_第二周作业_完成游戏导航栏

作业&#xff1a;游戏导航栏 成果展示&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0…

杭州克鲁斯机器人控制信号线缆故障维修攻略,快来了解一下!

克鲁斯机器人作为工业自动化的重要组成部分&#xff0c;其稳定运行对于生产效率至关重要。克鲁斯机器人控制信号线缆作为机器人与外部控制设备之间的桥梁&#xff0c;承担着传输指令和反馈信号的重要任务。 一、克鲁斯机器人控制信号线缆故障识别与诊断 故障现象&#xff1a;当…

Godot 学习笔记(4):一切以场景为中心

文章目录 前言场景搭建新建子场景最简单的按钮事件 手动控制场景手动加载场景添加多个场景对象更快速的获取脚本对象 删除多个场景对象脚本命名的问题 总结 前言 Godot的场景是C#与Godot最后的中间连接。我们解决了场景的加载&#xff0c;我们基本可以保证C#和godot之间的彻底…

JVM的知识

什么是JVM 1.JVM&#xff1a; JVM其实就是运行在 操作系统之上的一个特殊的软件。 2.JVM的内部结构&#xff1a; &#xff08;1&#xff09;因为栈会将执行的程序弹出栈。 &#xff08;2&#xff09;垃圾99%的都是在堆和方法区中产生的。 类加载器&#xff1a;加载class文件。…

处理 input type=‘hidden‘ 的事件触发

前言 在公司的 MES 系统&#xff08;摩尔元数N2&#xff09;做二次开发页面。某个字段在表单模型中配置为 弹出窗口 后、页面的对应字段样式自动转为 <input type"hidden"> &#xff0c;从而导致不能使用常规的 blur 、keydown 事件触发关联操作。下面是解决思…

【力扣刷题日记】603.连续空余座位

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 603.连续空余座位 表&#xff1a;Cinema 列名类型seat_idintfreebool Seat_id 是该表的自动递增主键列。 在…

【RabbitMQ | 第一篇】消息队列基础知识

文章目录 1.消息队列基础知识1.1什么是消息队列&#xff1f;1.2消息队列有什么用&#xff1f;&#xff08;结合项目说&#xff09;1.2.1异步处理1.2.2削峰/限流1.2.3降低系统耦合性1.2.4实现分布式事务 1.3消息队列的缺点1.4JMS和AMQP1.4.1 JMS的两种消息模型&#xff08;1&…

高效备考2024年AMC10:吃透2000-2023年1250道真题(限时免费送)

我们今天继续来随机看5道AMC10真题&#xff0c;以及详细解析&#xff0c;这些题目来自1250道完整的官方历年AMC10真题库。通过系统研究和吃透AMC10的历年真题&#xff0c;参加AMC10的竞赛就能拿到好名次。即使不参加AMC10竞赛&#xff0c;掌握了这些知识和解题思路后初中和高中…

#鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行

3 月 19 日&#xff0c;#鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行。 现场&#xff0c;深圳市南山区人民政府副区长李志娜发布《2024 年南山区支持鸿蒙原生应用发展首批政策措施清单》&#xff0c;从加强鸿蒙原生应用供给能力、推动鸿蒙原生应用产业集聚、完善鸿蒙原生…

扩容分区和文件系统(Linux)

在ECS控制台上扩容云盘容量后&#xff0c;对应分区和文件系统并未扩容&#xff0c;您还需要进入ECS实例内部继续扩容云盘的分区和文件系统&#xff0c;将扩容部分的容量划分至已有分区及文件系统内&#xff0c;使云盘扩容生效。本文为您介绍如何通过两个步骤完成Linux实例云盘的…

API 接口渗透测试

1 API 接口介绍 1.1 RPC&#xff08;远程过程调用&#xff09; 远程过程调用&#xff08;英语&#xff1a;Remote Procedure Call&#xff0c;缩写为 RPC&#xff09;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序&#xff0c;而程序员无…