Java多线程与高并发

1、什么是进程?什么是线程?

进程:进程是程序的基本执行实体;另外一种解释是进程是一个应用程序(1个进程是一个软件)。
线程:线程是操作系统能够进行运算调度的最下单位。它被包含在进程之中,是进程中的实际运作单位;是一个进程中的执行场景/执行单元。

注意:。一个进程可以启动多个线程

eg.
对于java程序来说,当在DOS命令窗口中输入:
java HelloWorld 回车之后。会先启动JVM,而JVM就是一个进程。

JVM再启动一个主线程调用main方法(main方法就是主线程)。
同时再启动一个垃圾回收线程负责看护,回收垃圾。

最起码,现在的java程序中至少有两个线程并发,一个是 垃圾回收线程,一个是 执行main方法的主线程。

2、进程和线程是什么关系?

进程:可以看做是现实生活当中的公司。

线程:可以看做是公司当中的某个员工。

注意:进程A和进程B的 内存独立不共享。

魔兽游戏是一个进程
酷狗音乐是一个进程
这两个进程是独立的,不共享资源。

线程A和线程B是什么关系?

在java语言中:
线程A和线程B,堆内存 和 方法区 内存共享。但是 栈内存 独立,一个线程一个栈。

eg.

假设启动10个线程,会有10个栈空间,每个栈和每个栈之间,互不干扰,各自执行各自的,这就是多线程并发。

eg.

火车站,可以看做是一个进程。
火车站中的每一个售票窗口可以看做是一个线程。
我在窗口1购票,你可以在窗口2购票,你不需要等我,我也不需要等你。所以多线程并发可以提高效率。


java中之所以有多线程机制,目的就是为了 提高程序的处理效率。

3、思考一个问题

使用了多线程机制之后,main方法结束,是不是有可能程序也不会结束?

main方法结束只是主线程结束了,主栈空了,其它的栈(线程)可能还在压栈弹栈。

4、分析一个问题

对于单核的CPU来说,真的可以做到真正的多线程并发吗?

对于多核的CPU电脑来说,真正的多线程并发是没问题的。4核CPU表示同一个时间点上,可以真正的有4个进程并发执行。

单核的CPU表示只有一个大脑:
不能够做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉。

对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于CPU的处理速度极快,多个线程之间频繁切换执行,给别人的感觉是:多个事情同时在做!!!

eg.

线程A:播放音乐

线程B:运行魔兽游戏

线程A和线程B频繁切换执行,人类会感觉音乐一直在播放,游戏一直在运行,
给我们的感觉是同时并发的。(因为计算机的速度很快,我们人的眼睛很慢,所以才会感觉是多线程!)


5、什么是真正的多线程并发?

t1线程执行t1的。
t2线程执行t2的。
t1不会影响t2,t2也不会影响t1。这叫做真正的多线程并发。

关于线程对象的生命周期(附图)?★★★★★

  1. 新建状态
  2. 就绪状态
  3. 运行状态
  4. 阻塞状态
  5. 死亡状态

在这里插入图片描述

线程构造方法

构造方法名备注
Thread()
Thread(String name)name为线程名字
创建线程第二种方式
Thread(Runnable target)
Thread(Runnable target, String name)name为线程名字

6、java语言中,实现线程有两种方式

第一种方式:

编写一个类,直接 继承 java.lang.Thread,重写 run方法。

  1. 怎么创建线程对象? new继承线程的类。
  2. 怎么启动线程呢? 调用线程对象的 start() 方法。

伪代码:

// 定义线程类
public class MyThread extends Thread{public void run(){}
}
// 创建线程对象
MyThread t = new MyThread();
// 启动线程。
t.start();

eg:

@SpringBootTest
public class Xiexingguo2ApplicationTests {
@Testvoid contextLoads() {MyThread t = new MyThread();// 启动线程//t.run(); // 不会启动线程,不会分配新的分支栈。(这种方式就是单线程。)t.start();// 这里的代码还是运行在主线程中。for (int i = 0; i < 1000; i++) {System.out.println("主线程--->" + i);}}
}
class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 1000; i++) {System.out.println("分支线程 = " + i);}}
}

注意

  • t.run() 不会启动线程,只是普通的调用方法而已。不会分配新的分支栈。(这种方式就是单线程。)
  • t.start() 方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了。
    这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了。线程就启动成功了。
    启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)。
    run方法在分支栈的栈底部,main方法在主栈的栈底部。run和main是平级的。

调用run()方法内存图:

在这里插入图片描述

调用start()方法内存图:

在这里插入图片描述

第二种方式:

编写一个类,实现 java.lang.Runnable 接口,实现run方法。

  • 怎么创建线程对象? new线程类传入可运行的类/接口。
  • 怎么启动线程呢? 调用线程对象的 start() 方法。

伪代码:

// 定义一个可运行的类
public class MyRunnable implements Runnable {public void run(){}
}
// 创建线程对象
Thread t = new Thread(new MyRunnable());
// 启动线程
t.start();

eg

public class ThreadTest03 {public static void main(String[] args) {Thread t = new Thread(new MyThread());t.start();for (int i = 0; i < 100; i++) {System.out.println("主线程--->" + i);}}
}
public class MyRunnable implements Runnable {public void run() {for (int i = 0; i < 100; i++) {System.out.println("分支线程 = " + i);}}
}

采用匿名内部类创建:

public class ThreadTest04 {public static void main(String[] args) {// 创建线程对象,采用匿名内部类方式。Thread t = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100; i++) {System.out.println("t线程---> " + i);}}});// 启动线程t.start();for (int i = 0; i < 100; i++) {System.out.println("main线程---> " + i);}}
}

注意:
第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。

7、获取当前线程对象、获取线程对象名字、修改线程对象名字

方法名作用
static Thread currentThread()获取当前线程对象
String getName()获取线程对象名字
void setName(String name)修改线程对象名字

当线程没有设置名字的时候,默认的名字是什么?

  • Thread-0
  • Thread-1
  • Thread-2
  • Thread-3

eg

public class MyThread2 extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {// currentThread就是当前线程对象。当前线程是谁呢?// 当t1线程执行run方法,那么这个当前线程就是t1// 当t2线程执行run方法,那么这个当前线程就是t2Thread currentThread = Thread.currentThread();System.out.println(currentThread.getName() + "-->" + i);//System.out.println(super.getName() + "-->" + i);//System.out.println(this.getName() + "-->" + i);}}
}

8、关于线程的sleep方法

方法名作用
static void sleep(long millis)让当前线程休眠millis秒
  1. 静态方法:Thread.sleep(1000);
  2. 参数是毫秒
  3. 作用: 让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用。
    这行代码出现在A线程中,A线程就会进入休眠。
    这行代码出现在B线程中,B线程就会进入休眠。
  4. Thread.sleep()方法,可以做到这种效果:间隔特定的时间,去执行一段特定的代码,每隔多久执行一次。

eg

public class ThreadTest05 {public static void main(String[] args) {//每打印一个数字睡1sfor (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + "--->" + i);// 睡眠一秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

9、关于线程中断sleep()的方法

方法名作用
void interrupt()终止线程的睡眠

eg

public class ThreadTest06 {public static void main(String[] args) {Thread t = new Thread(new MyRunnable2());t.setName("t");t.start();// 希望5秒之后,t线程醒来(5秒之后主线程手里的活儿干完了。)try {Thread.sleep(100*5);} catch (InterruptedException e) {e.printStackTrace();}// 终断t线程的睡眠(这种终断睡眠的方式依靠了java的异常处理机制。)t.interrupt();}
}
class MyRunnable2 implements Runnable{public void run() {System.out.println(Thread.currentThread().getName() + "---> begin");// 睡眠1年try {Thread.sleep(1000 * 60 * 60 * 24 * 365);} catch (InterruptedException e

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

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

相关文章

计算机的内存是如何实现的

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

Logit Standardization in Knowledge Distillation 知识蒸馏中的logit标准化

摘要 知识蒸馏涉及使用基于共享温度的softmax函数将软标签从教师转移到学生。然而&#xff0c;教师和学生之间共享温度的假设意味着他们的logits在logit范围和方差方面必须精确匹配。这种副作用限制了学生的表现&#xff0c;考虑到他们之间的能力差异&#xff0c;以及教师天生…

kubernetes多master集群架构

一、完成master02节点的初始化操作 master02环境准备&#xff0c;详细过程参考上一期博客环境准备 #添加主机映射 vim /etc/hosts 192.168.88.3 master01 192.168.88.8 master02 192.168.88.4 node01 192.168.88.5 node021、准备master02节点需要的文件 从 master01 节点上拷…

免费SSL证书:适合你的网站吗?

随着互联网的发展&#xff0c;安全性已经成为了网站运营不可或缺的一部分。而SSL证书作为保障网站数据传输安全的重要手段&#xff0c;被越来越多的网站所采纳。然而&#xff0c;对于很多小型网站或者个人博客来说&#xff0c;付费购买SSL证书可能会带来一定的经济压力。因此&a…

处理Mini-ImageNet数据集,用于分类任务

一、Mini-ImageNet数据集介绍 ImageNet 1000类的数据太大了&#xff0c;全部下载大概有100GB左右。 2016年google DeepMind团队从ImagNet数据集中抽取的一小部分&#xff08;大小约3GB&#xff09;制作了Mini-ImageNet数据集&#xff0c;共有100个类别&#xff0c;每个类别有…

搭建Kubernetes v1.20二进制集群——单Master和Node组件

前言 本文将介绍如何使用二进制文件手动搭建 Kubernetes v1.20 集群。通过这种方法&#xff0c;我们可以更好地理解 Kubernetes 的内部工作原理&#xff0c;并具备更大的灵活性和控制权。下面将逐步构建 Kubernetes 集群&#xff0c;并进一步了解其各个组件之间的交互和配置。…

Flash attention入门

一、目录 flash attentionGPU运算流程flash attention 原理flash attention 与 standard attention 时间/内存 对比。flash attention 算法实现比较flash attention 计算、memory-efficient attention 等不同内核下用时 二、实现 flash attention 目的&#xff1a; 提高运行速…

DiskANN数据布局

_mem.index.data&#xff1a;和sift_base.fbin一模一样。0-3字节是总向量数&#xff0c;4-7是每个向量的特征数。后面就是依次放置的每个向量。 _disk.index&#xff1a;是存储的图&#xff0c;但是不光包含图也包含原始向量。前4KB不知道存的是啥。从第0x1000开始存放的是原始…

Android 应用开发-实现将公共存储空间内的文件复制到应用的私用存储空间中

一、前言 几个月前&#xff0c;我用Android Studio给公司销售部门的同事开发了一款手机app&#xff0c;让同事们用自己的手机就能进行商品的扫码盘点操作&#xff0c;帮他们提高了工作效率&#xff0c;他们用了一段时间&#xff0c;反映还不错。不过前几天&#xff0c;销售部门…

OSG编程指南<二十三>:基于OSG+ImGui制作模型编辑器,实现三轴方向的实时平移、旋转和缩放变化

1、概述 在OSG的开发应用过程中&#xff0c;我们有时候总会纠结于使用MFC还是Qt来嵌入OSG窗口以便于后续的功能开发&#xff0c;毕竟选择一个合适的UI框架&#xff0c;对于后续的开发还是省去很多麻烦的。但对于初学者来说&#xff0c;可能对框架消息机制的不熟悉&#xff0c;尤…

SQL复习

SQL基础 包括&#xff1a; 数据查询&#xff1a;SELECT数据定义语言&#xff1a;CREATE、ALTER和DROP数据操纵语言&#xff1a;INSERT、UPDATE、DELETE数据控制语言&#xff1a;GRANT、REVOKE 特点&#xff1a; 综合统一高度非过程化面向集合既是独立的也是嵌入式语言 三…

2024年5月13号刷题相关事项个人总结

01.01.03 LeetCode 入门及攻略&#xff08;第 01 ~ 02 天&#xff09; 1. LeetCode 是什么 「LeetCode」 是一个代码在线评测平台&#xff08;Online Judge&#xff09;&#xff0c;包含了 算法、数据库、Shell、多线程 等不同分类的题目&#xff0c;其中以算法题目为主。我们…