java多线程_01

news2024/11/26 10:31:18

文章目录

      • 1. 线程的概念
        • 1. 程序
        • 2. 进程
        • 3. 线程
        • 4. Java程序的运行原理
        • 5. 并发与并行概念
          • 1. 并发
          • 2. 并行
          • 3. 并发编程和并行编程
      • 2. Java中的Thread线程类
          • 1. Thread类构造方法
          • 2. Thread类普通方法
          • 3. Thread类静态方法
          • 4. Thread类特殊方法
      • 3.线程的创建方式
          • 1. 继承Thread类
          • 2. 实现Runnable接口
          • 3. 实现Callable接口
          • 4. 多线程创建方式总结

1. 线程的概念

多线程是所有应用程序中都非常重要的特性,在Java中也是相同,一般情况多线程仅用于网络编程,服务器程序开发,以及常见的UI底层开发,或者系统底层开发,所以一般只要涉及到多线程开发那么程序就会非常复杂,代码逻辑也非常复杂
多线程的作用就是让程序在执行任务期间key同事操作多个任务或多个线程操作一个任务,从而达到提高执行效率
多线程程序:

  1. 现实生活:一个人跟一堆小姐姐聊天
  2. 软件:QQ,微信,迅雷,音乐软件

1. 程序

程序是一个静态的概念(未开启时),程序一般是指计算机中的一个可执行文件,例如:QQ,微信,等软件,当双击时会将对应的应用程序加载到内存中,并且开始执行程序并产生进程,程序开启后会生成进程

2. 进程

进程是一个正在运行的程序,当双击某个程序时会在内存中加载运行,所以进程就是在内存运行的程序,进程是动态的概念,程序加载过程就是在内存中会产生一个进程,并具有一定的功能,同时操作系统中允许开启多个进程,进程的最小执行单元是线程,进程的执行前提是必须要有一个线程执行,否则会程序终止

3. 线程

线程进程中最小的执行单元,主要赋值程序的运行,一个进程中至少要有一个线程执行,如果没有线程则进程就无法执行,导致进程结束
一个进程中允许启动多个线程(多个功能或任务),线程分为多线程和单线程

  1. 单线程:进程中只有一个执行的线程,任务的执行必须是顺序执行,当一个任务执行完毕后下一个任务才可以继续执行(依次执行)
  2. 多线程:进程中有多个执行的线程,任务可以同事执行,并且任务间不会存在互相干扰,互相影响的问题

4. Java程序的运行原理

Java的运行是由命令启动Java虚拟机(JVM),JVM启动后就等于是开起来一个进程,进程的开启是由类中的main方法执行,main方法是Java程序主线程,所有逻辑代码都是在main方法执行的,一般main方法就是程序入口
Java是多线程还是单线程?
答案是多线程。原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,JVM的启动其实是多线程的

5. 并发与并行概念

1. 并发

并发是指程序同一时间只能执行一条指令,多线程开启时会快速轮询切换(由CPU决定切换执行),从宏观上看是多个线程同时执行,但是在微观上并不是多个线程同时执行,而是将时间分为若干份,通过CPU切换执行(交替执行)
在同一个时间段内只能有一个线程执行,线程执行的途中其他线程则无法执行,这个是由CPU决定,三个线程不会出现同时执行的情况

2. 并行

并行是指程序同一时间可以执行多条指令,在同一个时限内宏观上看是同时执行,在微观上看也是同时执行,在一个时间片段内可以共同执行,这种效率也是最高
并行执行是在同一个时间片段内多条指令同时执行,同一个时间内三个线程可以同时执行并互不干扰
在这里插入图片描述

3. 并发编程和并行编程

并发编程与并行编程完全取决于CPU是否足够强大
如果CPU比较繁忙,资源不足时开启多个线程,那么是由CPU决定执行的线程应该是谁(多个线程抢夺CPU的执行权),谁抢夺到了谁执行,线程会尽可能抢夺执行权
如果CPU资源充足,那么开启多个线程或进程则可以分配不同的CPU内核(核心),此时多个进程中的多个线程则会同时执行,互不干扰,也不会出现抢夺CPU执行权的问题,每个线程都会分配独立的CPU内核运行
单核CPU最多只能并发编程,多核CPU可以实现并行编程

在这里插入图片描述
一个物理cpu(计算机主板上实际安装的cpu)可以有多个核心数,简称多核cpu;单核cpu是指一个cpu只有一个处理核心,双核cpu是指一个cpu具有两个处理核心,多核cpu是指一个cpu具有多个核心;计算机主板上可以安装多个物理cpu。

物理cpu内核总数=物理cpu数*每颗物理cpu核心数

逻辑cpu总数=总的物理cpu内核数*超线程数

这个电脑是六核十二线程,即一个物理cpu具有六个核心数属于多核cpu。

真正实现多线程效果的是:start0(),而不是run()方法,,很可惜的是start0()方法是本地方法由native关键字修饰,该方法由JVM调用,方法底层是由C/C++实现。

2. Java中的Thread线程类

Java中的线程启动需要使用Thread类的方法,此类用于创建并启动线程,其中定义了很多的构造方法与启动线程的方法,用于启动线程和定义线程规则等功能,同时还提供了静态获取方法以及普通获取方法,Thread类位于java.lang核心包中,所以不需要导包

1. Thread类构造方法
  1. public Thread():创建线程类对象
  2. public Thread(String name):创建线程类对象,并指定线程名称
  3. public Thread(Runnable target):创建线程类对象,并指定Runnable实现类
  4. public Thread(Runnable target, String name):创建线程类对象,并指定Runnable实现类以及指定线程名称
  5. public Thread(ThreadGroup group, String name):创建线程类对象,并指定线程分组以及指定线程名称
  6. public Thread(ThreadGroup group, Runnable target):创建线程类对象,并指定线程分组以及指定Runnable实现类
  7. public Thread(ThreadGroup group, Runnable target, String name):创建线程类对象,并指定线程分组以及指定Runnable实现类和指定线程名称
2. Thread类普通方法
  1. public long getId():获取当前线程对象ID
  2. public final String getName():获取当前线程对象名称
  3. public final int getPriority():获取当前线程优先级别
  4. public State getState():获取当前线程状态
  5. public final ThreadGroup getThreadGroup():获取当前线程分组
3. Thread类静态方法
  1. public static native Thread currentThread():获取当前正在执行的线程对象
4. Thread类特殊方法
  1. public void run():用于编写线程任务的方法(多线程执行的任务方法),继承后必须自定义实现的方法
  2. public synchronized void start():启动线程方法,当调用start方法时此方法会有JVM虚拟机调用执行run方法中的任务代码

3.线程的创建方式

1. 继承Thread类

创建一个类并继承Thread类,并重写run方法,在run方法中实现自己的线程任务,同时可以创建构造方法,调用父类的构造方法实现设置线程的信息

/**
 * 多线程创建方式一:继承Thread类重写run方法
 */
class CreateMethod1 extends Thread{

    public CreateMethod1(){}
    public CreateMethod1(String name){
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("createMethod1:"+i);
        }
    }
}
public class ThreadTest {

    public static void main(String[] args) {
        CreateMethod1 createMethod1 = new CreateMethod1("这个女生");
        createMethod1.start();
        System.out.println(createMethod1.getName());
        System.out.println("ID:"+createMethod1.getId());
        System.out.println("优先级别:"+createMethod1.getPriority());
        System.out.println("当前线程:"+Thread.currentThread());
        for (int i = 10; i < 20; i++) {
            System.out.println("threadTest:"+i);
        }
    }
}
2. 实现Runnable接口

创建一个类实现Runnable接口,并重写run方法,run方法就是线程任务方法

//实现Runnable接口重写run方法
class CreateMethod2 implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        System.out.println("次线程名称:"+thread.getName());
        System.out.println("次线程状态:"+thread.getState());
        System.out.println("次线程优先级:"+thread.getPriority());
        for (int i = 0; i < 10; i++) {
            System.out.println("实现Runnable接口:"+i);
        }
    }
}
public class ThreadTest2 {
    public static void main(String[] args) {
        CreateMethod2 createMethod2 = new CreateMethod2();
        Thread t1 = new Thread(createMethod2, "实现Runnable接口");
        t1.start();
        for (int i = 40; i < 50; i++) {
            System.out.println("主线程:"+i);
        }
    }
}
3. 实现Callable接口

创建一个类实现Callable接口,并重写call方法,call方法就是线程任务类,启动线程还需要创建一个任务FutureTask类,再创建Thread类启动线程
Callable接口的call方法具有返回值并且可以声明异常,call方法的返回值由FutureTask获取

class CreateMethod3 implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread thread = Thread.currentThread();
        System.out.println("次线程名称:"+thread.getName());
        System.out.println("次线程状态:"+thread.getState());
        System.out.println("次线程优先级:"+thread.getPriority());
        // 任务代码
        // 循环10次
        for (int i = 1; i <= 10; i++) {
            System.out.println("次线程执行..." + i);
        }
        // 返回值
        return "线程执行完毕";
    }
}
public class ThreadTest3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 创建Callable实现类
        Callable threadTest3 = new CreateMethod3();
        // 2. 创建FutureTask类
        FutureTask<String> futureTask = new FutureTask<>(threadTest3);
        // 3. 创建Thread类
        Thread thread = new Thread(futureTask,"创建线程方式3");
        // 接收返回值,get()方法用于接收Callable接口的返回值
        // 调用此方法时必须时线程已被启动的,如果是未启动则会造成程序阻塞等待
        // get方法调用后会等待接收返回值,等待途中其他代码不会执行
        thread.start();
        String res = futureTask.get();
        System.out.println("result = " + res);
        for (int i = 50; i < 60; i++) {
            System.out.println("主线程:"+i);
        }
    }
}

4. 多线程创建方式总结
  1. 继承Thread类
    1. 优点:实现简单
    2. 缺点:无返回值,异常不能声明抛出,Java是单继承,一旦继承Thread类则无法继承其他类
  2. 实现Runnable接口–>常用
    1. 优点:解决了单继承的问题,实现相对较为简单
    2. 缺点:无返回值,异常不能声明抛出
  3. 实现Callable接口
    1. 优点:解决了单继承问题,有返回值,异常可以声明抛出
    2. 缺点:实现较为复杂,接收返回值会造成程序阻塞,等待接收返回值,接收返回值后才可以继续执行

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

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

相关文章

C++ 仿函数(一)

目录 一、仿函数是什么&#xff1f; 二、仿函数的特点 1.仿函数在使用时&#xff0c;可以像普通函数那样调用, 可以有参数&#xff0c;可以有返回值 2.仿函数超出普通函数的概念&#xff0c;可以有自己的状态 ​编辑3.仿函数可以作为参数传递。 三、谓词 一元谓词示例&a…

38【源码】数据可视化:基于 Echarts + Python 动态实时大屏 - 全国图书零售监测数据

效果图展示 1.动态效果演示 2.静态切片效果图 一、确定需求方案 1.确定产品上线部署的屏幕LED分辨率 本案例基于16:9 屏宽比&#xff0c;F11全屏显示。 2.部署方式 浏览器打开播放&#xff0c;Chrome浏览器、360浏览器等。 二、整体架构设计 前端基于 Echarts开源库设计…

leetcode27.移除元素

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【LeetCode】 &#x1f353;希望我们一起努力、成长&#xff0c;共同进步。 &#x1f449;题目链接 题目描述 给你一个数组 nums 和一个…

从0开始学习数据库(持续更新)

一个数据库最重要的部分是什么&#xff1f; 关系型数据库mysql有着四大特性&#xff0c;原子性&#xff0c;隔离性&#xff0c;一致性&#xff0c;持久性。 kv数据库有着原子性&#xff0c;持久性&#xff0c;弱一致性。 可见&#xff0c;不管数据库的存储引擎是什么&#xff0…

LeetCode_递归_中等_138.复制带随机指针的链表

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random&#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的深拷贝。 深拷贝应该正好由 n 个全新节点组成&#…

vector源码解析及扩容优化

一、vector源码解析 没有任何一个东西可以在原地扩充&#xff0c;因为要了一块内存后&#xff0c;后面这块内存有可能被使用了&#xff0c;或者能不能用也不知道。链表可以保留原有节点&#xff0c;再将指针指向别处开辟的新内存&#xff0c;但这个也不算原地扩充。 对于vecto…

不需要等待列表,也不用魔法上网的Claude,能否比肩ChatGPT?

近期&#xff0c;国外Anthropic公司发布了Claude聊天机器人&#xff0c;堪比ChatGPT的最大竞争对手。一经推出&#xff0c;市场上就经常拿它俩来对比&#xff0c;因为推出Claude产品的Anthropic 公司是由多位前OpenAI前员工组成&#xff0c;两家公司&#xff0c;以及他们推出的…

ssm框架之SpringMVC:乱码问题

一种修改tomcat配置文件 如果tomcat乱码修改Tomcat的conf的server.xml文件加上 URIEncoding“UTF-8” 添加一个URIEncoding“UTF-8” tomcat 如果7.0 不这样设置&#xff0c;无论get还是post后台都显示乱码。tomcat如果是8.0版本&#xff0c;只有post后台显示是乱码 一种过滤…

Redis进阶

主要内容 Redis持久化Redis主从Redis哨兵Redis分片集群 Redis持久化 Redis有两种持久化的方案: RDB持久化AOF持久化 1. RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是把内存中的所…

HTML基本知识与常用标签的使用以及实现一个HTML版本个人简历

文章目录 HTML1. HTML结构1.1 认识标签1.1.2 HTML文件结构 2. HTML常见标签2.1 注释标签2.2 标题标签2.3 段落标签2.4 换行标签2.5 格式化标签2.6 图片标签2.7 超链接标签2.8 表格标签2.9 列表标签2.10 表单标签2.11 label 标签2.12 select 标签2.13 textarea 标签2.14 无语义标…

[架构之路-200]- 性能需求与性能分析:影响性能的主要因素

目录 前言&#xff1a;关于性能的几点说明 第一章 性能需求&#xff1a;提出各种性能指标 1.1 可靠性或可用性&#xff1a; stablity 1.2 处理能力或效率: Performance 1.2.1 指标是吞吐率 1.2.2 指标是响应时间&#xff1a; 1.2.3 指标是资源利用率 1.3 高并发性 1.…

FreeRTOS开启任务调度函数xPortStartScheduler详解

在FreeRTOS中&#xff0c;创建完任务后需要调用vTaskStartScheduler开启调度器&#xff0c;在这个函数主要就是创建空闲任务然后调用xPortStartScheduler函数开启任务的调度&#xff0c;本篇文章就以Cortex-M7为例来分析一下这个函数具体做了什么事&#xff0c;并深入理解其中的…

文献阅读:A Lite Distributed Semantic Communication System for Internet of Things

目录 动机&#xff1a;为什么作者想要解决这个问题&#xff1f;贡献&#xff1a;作者在这篇论文中完成了什么工作(创新点)&#xff1f;规划&#xff1a;他们如何完成工作&#xff1f;理由&#xff1a;通过什么实验验证它们的工作结果自己的看法 动机&#xff1a;为什么作者想要…

Python遍历大量表格文件并筛选出表格内数据缺失率低的文件

本文介绍基于Python语言&#xff0c;针对一个文件夹下大量的Excel表格文件&#xff0c;基于其中每一个文件内、某一列数据的特征&#xff0c;对其加以筛选&#xff0c;并将符合要求与不符合要求的文件分别复制到另外两个新的文件夹中的方法。 首先&#xff0c;我们来明确一下本…

【Linux】多线程 --- POSIX信号量+懒汉模式的线程池+其他常见锁

Linux system sprinkle flowers 文章目录 一、POSIX信号量1.阻塞队列实现的生产消费模型代码不足的地方&#xff08;无法事前得知临界资源的就绪状态&#xff09;2.信号量的理解3.初步看一下信号量的操作接口4.环形队列实现的生产消费模型5.环形队列的代码编写&#xff08;维持…

百度将凭借人工智能改变游戏规则并实现盈利?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 稳健的财务业绩 在2022年第四季度&#xff0c;百度&#xff08;BIDU&#xff09;的收入为48亿美元(331亿人民币)&#xff0c;比分析师预测的高出了1.72亿美元&#xff0c;但同比下降了约8%。从细分业务来看&#xff0c;百度…

Android:你真的会用Toast吗(介绍安卓好看简约的Toast快速解锁方法)

目录 概要 开源库地址 如何使用 1、首先我们现在根目录下的build.gradle中添加以下依赖 2、然后我们在我们的模块目录&#xff08;通常是app&#xff09;下的build.gradle中添加以下依赖 3、 然后这一步是可选的&#xff0c;你可以在你的app模块下任意位置&#xff0c;添加以下…

ANR原理篇 - ANR弹框是如何显示出来的

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、ANR弹框是如何显示流程1.1 找到弹框对应类1.2 查找AppNotRespondingDialog引用…

Python程序员职业现状分析,想提高竞争力,就要做到这六点

现今程序员群体数量已经高达几百万&#xff0c;学历和收入双高&#xff0c;月薪普遍过万。今天&#xff0c;我们就围绕90后程序员人群分析、职业现状、Python程序员分析等&#xff0c;进行较为全面的报告分析和观点论述。 一、程序员人群分析 人数规模上&#xff1a;截当前程…

javaweb系列-JSON对象、BOM对象、DOM对象

1.5.1.3 JSON对象 在 JavaScript 中自定义对象特别简单&#xff0c;其语法格式如下&#xff1a; <body><script>//自定义对象var user {name: "tom",age: 20,gendar: "male",eat: function () { //函数alert("吃饭啦");}};aler…