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

news2024/9/21 8:04:28

3.7. Lambda表达式

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

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

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

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

    TestLambda.java
        
    package com.hzs.basic.multithread;
    
    /**
     * @author Cherist Huan
     * @version 1.0
     */
    public class TestLambda {
    
        // 2、静态内部类
        static  class Like2 implements Ilike{
    
            @Override
            public void lambda() {
                System.out.println("Like-->2");
            }
        }
    
        public static void main(String[] args) {
            Ilike like = null;
    
            // 1、外部实现类1
            like = new Like();
            like.lambda();
    
            // 2、静态内部类
            like = new Like2();
            like.lambda();
    
            //3、局部内部类
            class Like3 implements Ilike{
    
                @Override
                public void lambda() {
                    System.out.println("Like-->3");
                }
            }
            like = new Like3();
            like.lambda();
    
            //4、匿名内部类,没有类的名称,必须借助接口或父类
            like = new Ilike() {
                @Override
                public 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、外部实现类1
     class Like implements Ilike{
    
        @Override
        public 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();
        @Override
        public 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{
    
        @Override
        public 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.coloradmin.cn/o/1536100.html

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

相关文章

山东省大数据局副局长禹金涛一行莅临聚合数据走访调研

3月19日&#xff0c;山东省大数据局党组成员、副局长禹金涛莅临聚合数据展开考察调研。山东省大数据局数据应用管理与安全处处长杨峰&#xff0c;副处长都海明参加调研&#xff0c;苏州市大数据局副局长汤晶陪同。聚合数据董事长左磊等人接待来访。 调研组一行参观了聚合数据展…

安装OneNote for Win10 | Win10/Win11

前言 PC端的OneNote分为2个版本&#xff0c;分别是Microsoft Store版本和Office版本&#xff0c;Microsoft Store版本即为OneNote for Win10&#xff0c;此版的OneNote有最近笔记功能&#xff0c;但检索功能不如Office版本&#xff0c;个人认为2个版本各有优劣。 但OneNote f…

详细剖析多线程(更新中...)

文章目录 前言一、认识线程1.1线程概念1.2为什么要有线程1.3线程和进程的区别&#xff08;经典面试题&#xff09; 二、创建线程2.1继承 Thread 类,重写run2.2实现 Runnable 接口,重写run2.3继承 Thread 类,重写run&#xff0c;匿名内部类2.4实现 Runnable 接口,重写run&#x…

WEB 表单练习题

任务如图&#xff1a; <html><head><meta charest"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><body><table width"…

解决nginx报错nginx: [emerg] unknown log format main in 的方法

目录 一、故障描述1&#xff1a; 重启nginx是出现了如下错误 解决办法 二、故障描述2&#xff1a; 解决办法&#xff1a; 三、nginx介绍​ 四、nginx原理 五、nginx.conf配置文件 六、nginx负载均衡 七、正向代理、反向代理 一、故障描述1&#xff1a; 在添加Nginx的…

【WEEK4】 【DAY3】整合SSM框架之功能实现—修改、删除数据【中文版】

2024.3.20 Wednesday 接上文【WEEK4】 【DAY2】整合SSM框架之功能实现—总览、添加数据【中文版】 目录 7.6.修改功能7.6.1.修改BookController.java7.6.2.修改allBook.jsp7.6.3.新建updateBook.jsp7.6.4.修改MyBatis-config.xml7.6.5.运行 7.7.删除功能7.7.1.修改BookContro…

网络原理(4)——TCP协议的特性

目录 一、滑动窗口 1、ack丢了 2、数据丢了 二、流量控制&#xff08;流控&#xff09; 三、拥塞控制 拥塞窗口动态变化的规则 四、延时应答 五、捎带应答 六、面向字节流 七、异常情况 &#xff08;1&#xff09;进程崩溃了 &#xff08;2&#xff09;其中一方关机…

Ubuntu系统提示“/dev/mmcblk0p1 分区满了‘以及磁盘空间不够的处理办法

查看boot分区使用空间&#xff1a; df 查看已安装的内核版本&#xff1a; dpkg --get-selections | grep linux &#xff08;其中带image的一般就是旧版本&#xff0c;deinstall代表已经删除的旧版本&#xff0c;install代表还未删除的旧版本内核&#xff09; 查看系统当前…

基于java+springboot+vue实现的健身房管理系统(文末源码+Lw+ppt)23-523

摘 要 健身房管理的以往工作流程繁杂、多样、管理复杂与设备维护繁琐。而如今计算机已完全能够胜任健身房管理工作&#xff0c;而且更加准确、方便、快捷、高效、清晰、透明&#xff0c;它完全可以克服以上所述的不足之处。这将给查询信息和管理带来很大的方便&#xff0c;从…

晶体管测试仪系统能测 IGBT. Mosfet. Diode. BJT......

晶体管测试仪系统能测试很多电子元器件的静态直流参数&#xff08;如击穿电压V(BR)CES/V(BR)DSs、漏电流ICEs/lGEs/IGSs/lDSs、阈值电压/VGE(th)、开启电压/VCE(on)、跨导/Gfe/Gfs、压降/Vf、导通内阻Rds(on)&#xff09;。 测试种类覆盖 7 大类别26分类&#xff0c;包括“二极…

Redis 更新开源许可证 - 不再支持云供应商提供商业化的 Redis

原文&#xff1a;Rowan Trollope - 2024.03.20 未来的 Redis 版本将继续在 RSALv2 和 SSPLv1 双许可证下提供源代码的免费和宽松使用&#xff1b;这些版本将整合先前仅在 Redis Stack 中可用的高级数据类型和处理引擎。 从今天开始&#xff0c;所有未来的 Redis 版本都将以开…

力扣454. 四数相加 II

思路&#xff1a;把四个数组拆成两对&#xff0c;两个分别相加&#xff0c;记录第一对的相加结果进map里&#xff0c;再把第二对数组 0-nums2-nums4 去map里面找出现了几次&#xff0c;这题不用对重复的四元组去重&#xff0c;所以出现多次都有效。 class Solution {public int…

Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证

昨日&#xff0c;Redis 官方宣布了一项重要变更&#xff1a;他们将修改开源协议&#xff0c;未来所有版本将采用 “源代码可用” 的许可证。 具体来说&#xff0c;Redis 不再使用 BSD 3-Clause 开源协议进行分发。从 Redis 7.4 版本开始&#xff0c;Redis 将采用 SSPLv1 和 RSA…

探索大广赛获奖作品:职场设计风云的精彩篇章

2024第16届全国大学生创意广告大赛正在火热进行中&#xff0c;今天就与大家分享一些平面类往届优秀获奖作品&#xff0c;仅供参考~灵感慢慢&#xff0c;不要错过哦&#xff01; 大广赛命题素材下载&#xff1a; 下载地址https://js.design/f/Jspbti?sourcecsdn&planbtts…

Go语言学习Day1:什么是Go?

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、走近Go①Go语言的Logo②Go语言的创始人③Go语…

excel文件可以转成word文件吗?汇帮PDF转换器帮你实现excel转word

将Excel文件转换为Word文档是一个相对简单的任务&#xff0c;但在执行过程中需要注意一些细节&#xff0c;以确保转换后的文档格式正确、内容清晰。下面将详细介绍用汇帮PDF转换器将Excel转Word的步骤和注意事项。 一、Excel文件准备 在进行转换之前&#xff0c;首先确保Excel…

软考高级:UML 图-状态图概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

科研学习|论文解读——通过调查实验了解公民对政府财政信息的认知(GIQ,2022)

原文题目 Understanding citizens perception of government fiscal information through a survey experiment 摘要 州和地方政府定期向公众披露财务信息&#xff0c;以便公开承认政府当前的财务状况。此类披露的目的是实现问责制并让公民了解政府的财务决策。(背景&#xff0…

MySQL之索引与事务

一 索引的概念 一种帮助系统查找信息的数据 数据库索引 是一个排序的列表&#xff0c;存储着索引值和这个值所对应的物理地址无须对整个表进行扫描&#xff0c;通过物理地 址就可以找到所需数据是表中一列或者若干列值排序的方法 需要额外的磁盘空间 索引的作用 1 数据库…

mysqly索引(explain 执行计划)

关键词 执行计划 EXPLAIN 语句查看mysql 优化后的语句 show warnings;EXPLAIN 执行后&#xff0c;各列的含义 要点&#xff1a; select_type 如何查询 表type 如何查询 行key 如何使用 索引key_len 索引 使用多少rows 行 预计使用多少extra 表 的额外信息 1.id id列的编…