Juc01_多线程概述、四种实现方式、常用方法API、生命周期、买票案例、synchronized锁(一)

简介: ①. 多线程的概述(面试高频问点)②. 多线程的实现方式①. 继承Thread②. 实现Runnable接口

说明


(1). 关于synchronized关键字底层原理参考如下文章


(2). Juc18_Java内存模型、对象头Mark Word、实例数据、对齐填充、谈谈new Object( )占多大内存


(3). Juc19_从字节码角度看synchronize、Monitor类、monitorenter、monitorexit


(4). Juc20_Synchronized锁升级、无锁、偏向锁、轻量级锁、重量级锁、锁消除、锁粗化


①. 多线程的概述(面试高频问点)


  • ①. 为什么使用多线程及其重要


摩尔定律失效(硬件方面):


(1). 集成电路上可以容纳的晶体管数目在大约每经过18个月便会增加一倍,可是从2003年开始CPU主频已经不再翻倍,而是采用多核而不是更快的主频


(2). 在主频不再提高且核数不断增加的情况下,要想让程序更快就要用到并行或并发编程

高并发系统,异步+回调的生产需求(软件方面)


②. 进程、线程、管程(monitor 监视器)


线程就是程序执行的一条路径,一个进程中可以包含多条线程


多线程并发执行可以提高程序的效率,可以同时完成多项工作


举例:


[你打开一个word就是一个进程开启了,这个时候你重启后在打开word,这个时候有一个点击恢复的按钮,这就是一个线程,可能这个线程你看不到,你打字的时候,单词打错了,word中会有一个波浪线,这也是一个线程]


管程:Monitor(监视器),也就是我们平时所说的锁


(Monitor其实是一种同步机制,它的义务是保证(在同一时间)只有一个线程可以访问被保护的数据和代码)


JVM中同步时基于进入和退出的监视器对象(Monitor,管程),每个对象实例都有一个Monitor对象。


Monitor对象和JVM对象一起销毁,底层由C来实现


③. 多线程并行和并发的区别


并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行(需要多核CPU)


并发是指两个任务都请求运行,而处理器只能接收一个任务,就是把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行(12306抢票的案例)


④. wait | sleep的区别?功能都是当前线程暂停,有什么区别?


wait放开手去睡,放开手里的锁;wait是Object类中的方法


sleep握紧手去睡,醒了手里还有锁 ;sleep是Thread中的方法


⑤. synchronized 和 lock的区别?


(1). 原始构成
 a. synchronized是关键字属于JVM层面
 monitor对象,每个java对象都自带了一个monitor,需要拿到monitor对象才能做事情
 monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖monitor对象,
 只能在同步块或方法中才能调用wait/notify等方法),进入
 monitorexit:退出
 b. lock是api层面的锁,主要使用ReentrantLock实现
(2). 使用方法
 a. synchronized不需要用户手动释放锁,当synchronized代码完成后系统会自动让线程释放
对锁的占用
 b. ReentrantLock则需要用户手动释放锁若没有主动释放锁,就有可能会导致死锁的现象
(3). 等待是否可中断?
 a. synchronized不可中断,除非抛出异常或者正常运行完成
 b. ReentrantLock可中断
 (设置超时时间tryLock(long timeout,TimeUnit unit),调用interrupt方法中断)
(4). 加锁是否公平
 a. synchronized非公平锁
 b. ReentrantLock两者都可以,默认是非公平锁,构造方法可以传入boolean值,true为公平锁,
 false为非公平锁
(5). 锁绑定多个Condition
 a.synchronized没有
 b.ReentrantLock用来实现分组唤醒需要唤醒线程们,可以精确唤醒,而不是像synchronized要么
 随机唤醒一个\要么多个


②. 多线程的实现方式


①. 继承Thread


  //注意:打印出来的结果会交替执行
  public class ThreadDemo{
      public static void main(String[] args) {
          //4.创建Thread类的子类对象
          MyThread myThread=new MyThread();
          //5.调用start()方法开启线程
          //[ 会自动调用run方法这是JVM做的事情,源码看不到 ]
          myThread.start();
          for (int i = 0; i < 100; i++) {
              System.out.println("我是主线程"+i);
          }
      }
  }
  class MyThread extends Thread{
      //2.重写run方法
      public void run(){
          //3.将要执行的代码写在run方法中
         for(int i=0;i<100;i++){
             System.out.println("我是线程"+i);
         }
      }
  }


②. 实现Runnable接口


  • ①. 源码分析如下:


微信图片_20220106173408.png


public class RunnableDemo {
    public static void main(String[] args) {
        //4.创建Runnable的子类对象
        MyRunnale mr=new MyRunnale(); 
        //5.将子类对象当做参数传递给Thread的构造函数,并开启线程
        //MyRunnale taget=mr; 多态
        new Thread(mr).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("我是主线程"+i);
        }
    }
}
//1.定义一个类实现Runnable
class MyRunnale implements Runnable{
    //2.重写run方法
    @Override
    public void run() {
        //3.将要执行的代码写在run方法中
        for (int i = 0; i < 1000; i++) {
            System.out.println("我是线程"+i);
        }
    }
}


②. 两种实现多线程方式的区别


  (1).查看源码
  a.继承Thread:由于子类重写了Thread类的run(),当调用start()时,直接找子类的run()
  方法
    b.实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用
 run()方法时内部判断成员变量Runnable的引用是否为空,不为空编译时看的是Runnable的run(),
 运行时执行的是子类的run()方法
    (2).继承Thread
    a.好处是:可以直接使用Thread类中的方法,代码简单
    b.弊端是:如果已经有了父类,就不能用这种方法
    (3).实现Runnable接口
    a.好处是:即使自己定义的线程类有了父类也没有关系,因为有了父类可以实现接口,而且接口
可以多现实的
    b.弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,
代码复杂


相关文章
|
11天前
|
JSON 数据可视化 API
Python 中调用 DeepSeek-R1 API的方法介绍,图文教程
本教程详细介绍了如何使用 Python 调用 DeepSeek 的 R1 大模型 API,适合编程新手。首先登录 DeepSeek 控制台获取 API Key,安装 Python 和 requests 库后,编写基础调用代码并运行。文末包含常见问题解答和更简单的可视化调用方法,建议收藏备用。 原文链接:[如何使用 Python 调用 DeepSeek-R1 API?](https://apifox.com/apiskills/how-to-call-the-deepseek-r1-api-using-python/)
|
7天前
|
存储 缓存 关系型数据库
MySQL底层概述—3.InnoDB线程模型
InnoDB存储引擎采用多线程模型,包含多个后台线程以处理不同任务。主要线程包括:IO Thread负责读写数据页和日志;Purge Thread回收已提交事务的undo日志;Page Cleaner Thread刷新脏页并清理redo日志;Master Thread调度其他线程,定时刷新脏页、回收undo日志、写入redo日志和合并写缓冲。各线程协同工作,确保数据一致性和高效性能。
MySQL底层概述—3.InnoDB线程模型
|
4月前
|
测试技术 API 项目管理
API测试方法
【10月更文挑战第18天】API测试方法
94 1
|
7天前
|
存储 搜索推荐 API
淘宝拍立淘按图搜索API接口系列概述
淘宝拍立淘按图搜索API接口允许用户通过上传图片或拍摄实物来搜索相似或相同的商品。这一功能主要依赖于图像识别技术,系统会对上传的图片进行分析和处理,提取出商品的特征信息,并在淘宝的商品数据库中进行匹配搜索,最终返回与上传图片相似或相同的商品列表。
|
1月前
|
存储 监控 Java
JAVA线程池有哪些队列? 以及它们的适用场景案例
不同的线程池队列有着各自的特点和适用场景,在实际使用线程池时,需要根据具体的业务需求、系统资源状况以及对任务执行顺序、响应时间等方面的要求,合理选择相应的队列来构建线程池,以实现高效的任务处理。
120 12
|
2月前
|
JSON 安全 API
淘宝商品详情API接口(item get pro接口概述)
淘宝商品详情API接口旨在帮助开发者获取淘宝商品的详细信息,包括商品标题、描述、价格、库存、销量、评价等。这些信息对于电商企业而言具有极高的价值,可用于商品信息展示、市场分析、价格比较等多种应用场景。
|
2月前
|
数据采集 监控 数据挖掘
常用电商商品数据API接口(item get)概述,数据分析以及上货
电商商品数据API接口(item get)是电商平台上用于提供商品详细信息的接口。这些接口允许开发者或系统以编程方式获取商品的详细信息,包括但不限于商品的标题、价格、库存、图片、销量、规格参数、用户评价等。这些信息对于电商业务来说至关重要,是商品数据分析、价格监控、上货策略制定等工作的基础。
|
2月前
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
407 5
|
3月前
|
JSON BI API
商城上货API接口的实战案例
在商城上货过程中,API接口扮演着至关重要的角色。以下是对商城上货API接口的实战分析,涵盖其主要功能、类型、安全性以及实战案例等方面。
|
3月前
|
XML 数据可视化 API
商品详情数据实战案例,API接口系列
淘宝商品详情数据在电商领域具有广泛的应用价值,而淘宝商品详情API接口则为开发者提供了获取这些数据的重要途径。通过合理利用这些接口和数据,可以提升业务效率、优化用户体验,为电商行业的发展注入新的活力。