线程学习贴
创始人
2025-05-28 12:00:39

1. 线程相关概念

1.1 程序

在这里插入图片描述

1.2 进程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 线程

在这里插入图片描述
在这里插入图片描述

1.4 并发和并行

在这里插入图片描述
如何查看cpu的个数:资源管理器
在这里插入图片描述
设备管理器方式
在这里插入图片描述

java查看处理器个数

@Test
public void testCpuNum(){Runtime runtime = Runtime.getRuntime();int i = runtime.availableProcessors();System.out.println("处理器个数为:"+i);
}

2. 线程的基本使用

2.1 创建线程的两种方式

在这里插入图片描述

2.2 应用案例(继承Thread类)

在这里插入图片描述
多线程图示
在这里插入图片描述
java中jconsole的使用:
控制台输入
在这里插入图片描述
找到对应的进程
在这里插入图片描述
在这里插入图片描述

package com.hspedu.threaduse;/*** 演示通过继承Thread 类创建线程*/
public class Thread01 {public static void main(String[] args) throws InterruptedException {//创建Cat对象,可以当做线程使用Cat cat = new Cat();//读源码/*(1)public synchronized void start() {start0();}(2)//start0() 是本地方法,是JVM调用, 底层是c/c++实现//真正实现多线程的效果, 是start0(), 而不是 runprivate native void start0();*/cat.start();//启动线程-> 最终会执行cat的run方法//cat.run();//run方法就是一个普通的方法, 没有真正的启动一个线程,就会把run方法执行完毕,才向下执行//说明: 当main线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行//这时 主线程和子线程是交替执行..System.out.println("主线程继续执行" + Thread.currentThread().getName());//名字mainfor(int i = 0; i < 60; i++) {System.out.println("主线程 i=" + i);//让主线程休眠Thread.sleep(1000);}}
}//说明
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的run方法
/*@Overridepublic void run() {if (target != null) {target.run();}}*/class Cat extends Thread {int times = 0;@Overridepublic void run() {//重写run方法,写上自己的业务逻辑while (true) {//该线程每隔1秒。在控制台输出 “喵喵, 我是小猫咪”System.out.println("喵喵, 我是小猫咪" + (++times) + " 线程名=" + Thread.currentThread().getName());//让该线程休眠1秒 ctrl+alt+ttry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(times == 80) {break;//当times 到80, 退出while, 这时线程也就退出..}}}
}

1.start0() 是本地方法,是JVM调用, 底层是c/c++实现
2.真正实现多线程的效果, 是start0(), 而不是 run
private native void start0();
3.当一个类继承了 Thread 类, 该类就可以当做线程使用
4.我们会重写 run方法,写上自己的业务代码
5.run Thread 类 实现了 Runnable 接口的run方法

2.3 应用案例(实现Runnable接口)

在这里插入图片描述

package com.hspedu.threaduse;/**
* @version 1.0
* 通过实现接口Runnable 来开发线程
*/
public class Thread02 {public static void main(String[] args) {Dog dog = new Dog();//dog.start(); 这里不能调用start//创建了Thread对象,把 dog对象(实现Runnable),放入ThreadThread thread = new Thread(dog);thread.start();//        Tiger tiger = new Tiger();//实现了 Runnable
//        ThreadProxy threadProxy = new ThreadProxy(tiger);
//        threadProxy.start();}
}class Animal {
}class Tiger extends Animal implements Runnable {@Overridepublic void run() {System.out.println("老虎嗷嗷叫....");}
}//线程代理类 , 模拟了一个极简的Thread类
class ThreadProxy implements Runnable {//你可以把Proxy类当做 ThreadProxyprivate Runnable target = null;//属性,类型是 Runnable@Overridepublic void run() {if (target != null) {target.run();//动态绑定(运行类型Tiger)}}public ThreadProxy(Runnable target) {this.target = target;}public void start() {start0();//这个方法时真正实现多线程方法}public void start0() {run();}
}class Dog implements Runnable { //通过实现Runnable接口,开发线程int count = 0;@Overridepublic void run() { //普通方法while (true) {System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());//休眠1秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (count == 10) {break;}}}
}

代理模式,有静态代理和动态代理
通过Thread含参构造实现的线程创建底层实际运用了代理模式

2.4 线程使用案例(多线程执行)

在这里插入图片描述

/*** main线程启动两个子线程*/
public class Thread03 {public static void main(String[] args) {T1 t1 = new T1();T2 t2 = new T2();Thread thread1 = new Thread(t1);Thread thread2 = new Thread(t2);thread1.start();//启动第1个线程thread2.start();//启动第2个线程//...}
}class T1 implements Runnable {int count = 0;@Overridepublic void run() {while (true) {//每隔1秒输出 “hello,world”,输出10次System.out.println("hello,world " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 60) {break;}}}
}class T2 implements Runnable {int count = 0;@Overridepublic void run() {//每隔1秒输出 “hi”,输出5次while (true) {System.out.println("hi " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 50) {break;}}}
}

2.5 线程的理解

在这里插入图片描述
在这里插入图片描述

自我思考:
多线程是什么,为什么要使用多线程,有什么好处
首先多线程可以理解为:假设一个程序有多个功能,如果只有一个主线程(一个人)执行,那么从头到尾都是一个线程(人)在干活,现在有了多线程,我可以将一个程序交给不同的线程(人)去完成对应的功能,比如A线程负责下载,B线程负责上传,这个操作是可以同时进行的,大大提升了程序的效率

2.6 继承 Thread vs 实现 Runnable 的区别

在这里插入图片描述

3. 线程安全问题

3.1 售票案例

在这里插入图片描述

package com.hspedu.ticket;/*** 使用多线程,模拟三个窗口同时售票100张*/
public class SellTicket {public static void main(String[] args) {//测试
//        SellTicket01 sellTicket01 = new SellTicket01();
//        SellTicket01 sellTicket02 = new SellTicket01();
//        SellTicket01 sellTicket03 = new SellTicket01();
//
//        //这里我们会出现超卖..
//        sellTicket01.start();//启动售票线程
//        sellTicket02.start();//启动售票线程
//        sellTicket03.start();//启动售票线程System.out.println("===使用实现接口方式来售票=====");SellTicket02 sellTicket02 = new SellTicket02();new Thread(sellTicket02).start();//第1个线程-窗口new Thread(sellTicket02).start();//第2个线程-窗口new Thread(sellTicket02).start();//第3个线程-窗口}
}//使用Thread方式
class SellTicket01 extends Thread {private static int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠50毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"+ " 剩余票数=" + (--ticketNum));}}
}//实现接口方式
class SellTicket02 implements Runnable {private int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠50毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"+ " 剩余票数=" + (--ticketNum));//1 - 0 - -1  - -2}}
}

相关内容

热门资讯

【C++初阶】10 .习题1 2022-09-16_命名空间 1. 命名空间的概念 下面关于C++命名空间描述错...
基于bearpi的智能小车--... 基于bearpi的智能小车--Qt上位机设计 前言一、界面原型1.主界面2.网络配置子窗口模块 二、...
三、Java核心技术(进阶)-... 一、概念 国际化编程:通过一套软件适配多个语言包。 二、相关函数 java.util....
水声功率放大器与宽带匹配技术研...   作为声呐设备重要的一份子,水声信号发射机承担着非常重要的作用。水声信号发射机其实是...
【C++】12.继承 1.引入继承 学生管理系统 学生 老师 社管阿姨 保安大叔 4个类 4个类有很多重复的东西...
LINUX中atd和crond... 一、atd与crond的区别1、运行方式不同,at只运行一次,而cron...
C++数据结构 —— 哈希表、... 目录 1.哈希概念 1.1哈希函数 1.2哈希冲突 2.闭散列实现 3.开散列实现 4.容器的封装 ...
Streamlit 学习笔记1 Streamlit 学习笔记1 文章目录Streamlit 学习笔记1首先 安利下streamlit...
基层区域应用平台为目标开发的基... 系统特点:  JAVA语言开发,MYSQL数据库,B/S架构 基于云计算...
数智链接,新一代校园招聘解决方... 疫情3年市场巨变,00后新生代初登上求职舞台,中和作用下,...
面试官:rem和vw有什么区别 "rem" 和 "vw"的区别 "rem" 和 "vw" 都是用于网页设计的CSS单位。 "rem"...
Pytest自动化测试框架完美... 简介 Allure Framework是一种灵活的、轻量级、多语言测试报告工具。 不仅可以以简洁的网...
华为nat配置实验:内网能够访... 一 需求分析1.1 需求 公司A在北京,公司B在上海,本次实验仅仅模拟局...
事务日志与 两阶段提交 文章目录 Redo Logredo的优点redo的组成redo的整体流程不同刷盘策略演示 Undo ...
【目标跟踪算法】Strong ... 1. Strong SORT算法的背景和概述 Strong SORT算法基于经典的Deep SORT...
Lock接口——JUC随记2 1、synchronized 1.1、synchronized的三种应用方式 一. 修饰实例方法&#...
IO流之字符流 文章目录1. 字符流概述2. 编码表3. 编码和解码4. 写数据的方式5. 读数据的方式6. 转换流...
C语言的灵魂---指针(基础) C语言灵魂指针1.什么是指针?2.指针的大小3.指针的分类3.1比较常规的指针类型3....
【华为OD机试真题JAVA】最... 标题:最优策略组合下的总的系统消耗资源数问题 | 时间限制:1秒 | 内存限制:262144K | ...
MATLAB | 给热图整点花... 前段时间写的特殊热图绘制函数迎来大更新,基础使用教程可以看看这一篇: h...
小知识·BitTorrent ... BitTorrent 简介从 P2P 说起经常在网上飙车的老司机应该都知道 BT 下载,...
Redis和Memcached...         对于大多数的系统服务来说,缓存是提高性能和可伸缩性的关键。一般情况下我...
[牛客算法总结]:重建二叉树    标签: 二叉树、DFS、先序遍历、中序遍历、递归   题目: 给定...
VS Code 将推出更多 A... 大家好,欢迎来到我们的二月更新!我们将为您带来与 JUnit 5 并行测...
为什么要推荐使用pnpm 在谈起pnpm时先来聊一聊之前的npm和yarn有什么存在的问题  npm2 在npm3之前我们安装...
多线程开发 文章目录多线程开发1. Thread创建多线程2. ThreadPoolExecutor创建进程池a...
闪存系统性能优化方向?NAND... Hello 大家好, 我是元存储~ 目录 前言 1. 提升效果 2. Cache Re...
关于复杂链表的复制问题(力扣) 上面我们已经说了两个关于链表的实现了,其中一个是单链表,另外一个是双向带...
STM32学习(二) 常用开发工具简介 安装仿真器驱动 DAP仿真器免驱ST LINK仿真器驱动安装方法:...
K8s配置jenkins Ma... 1、k8s安装jenkins 以阿里云的ACK为例 A、在有状态点击镜像创建,配置自己...