Java线程概念详解

线程

在这里插入图片描述

概念

1.程序:未解决某种问题,使用计算机语言编写的一些列指令(代码)的集合

2.进程:正在运行的程序(被加载到内存中),是操作系统进行资源分配的最小单位

3.线程:进程可以进一步细化为线程(比进程更小)且线程是隶属于进程的,是操作系统执行的最小的执行单元 也是cpu进行任务调度的最小单位

  • 如 :运行的QQ也是一个进程,操作系统就会为这个进程分配资源 一个聊天窗口就是一个线程,线程隶属于进程

tips:早期是没有线程的,是以进程为单位执行的,进程的单位比较大,当一个进程运行时,其他进程就不能执行了,所以后来,将进程中的多个任务细化为线程,cpu的执行单位,也是从进程进化为更小的线程

总结

  1. 一个进程可以包含多个线程
  2. 一个线程只能隶属于一个进程,线程不能脱离进程单独独立运行
  3. 一个进程中至少有一个线程,即主线程,javamian方法就是用来启动主线程
  4. 在主线程中可以创建并启动其他线程,所有线程都共享进程的内存资源
  5. 所有线程都共享进程资源

Thread类

JavaThread表示线程,提供了许多的方法,来对线程的控制,可以通过继承Thread 类来实现线程

Thread常用方法

  • Thread.currentThread();
    • 获取当前运行的线程
  • run();
    • 线程要执行的任务
  • start();
    • 启动Java线程
  • setName(String name);
    • 设置线程名字
  • (String)getName();
    • 获取线程名字
  • getPriority();
    • 获取线程优先级
  • setPriority();
    • 设置线程优先级 1~10一般线程默认优先 5
  • sleep(long ms);
    • 设置线程休眠
  • join();
    • 让其他线程等待这个线程结束后,其他线程再执行

Thread构造方法

  • new Thread(Runnable runnable);
    • 接受一个任务对象
  • new Thread(Runnable runnable,String name);
    • 接受一个对象 并为对象设置名字

使用上面方法进行实例

线程1
public class MyThread extends Thread{//重写run方法,在run中执行我们要执行的方法@Overridepublic void run() {for(int i=0;i<10000;i++){System.out.println("循环main"+i);}}}
线程2
public class MyThread2 extends Thread {@Overridepublic void run() {for(int i=0;i<10000;i++){System.out.println("循环main2"+i);}}
}
public class 线程 {public static void main(String[] args) {for(int i=0;i<10000;i++){System.out.println("循环1 "+i);}for(int i=0;i<10000;i++){System.out.println("循环2 "+i);}for(int i=0;i<10000;i++){System.out.println("循环3 "+i);}for(int i=0;i<10000;i++){System.out.println("循环4 "+i);}/*这样不管怎么执行都是单线程,从上到下依次执行,所以如果想在java程序中有几件不想管的事件同时执行可以在java中创建线程,把一些需要执行的任务放在线程中执行,这样就拥有让cup执行的权利*/MyThread myThread = new MyThread();//调用start方法让程序多线程进行,重写run方法但不能调用run,不然只是普通方法的调用,依然是单线程myThread.start();MyThread2 myThread2 = new MyThread2();myThread2.start();}}

image-20231207203645612

观察结果 可知 MyThreadMyThread2是同时进行的

Runnable接口

Java中我们也可以实现Runnable接口来进行对线程的实现

思路.

  • 创建一个类 实现Runnable接口 重写run方法

  • 在main函数使用Thread构造方法传入Runnable对象

  • public class MyTask implements Runnable{@Overridepublic void run() {for(int i=0;i<10;i++){System.out.println("啊");}}
    }
    
  • MyTask myTask = new MyTask();//创建一个线程Thread thread = new Thread(myTask);
    

Callable接口

Java中也可以实现Callable接口 重写 call()方法 来对线程的实现

思路.

  • 重写call()方法 call()方法有返回值 可以抛出异常,还可以处理不同类型
  • 依然使用Thread构造方法来创建一个线程

关于线程的其他概念

线程生命周期

从线程到销毁期间经历五个状态

image-20231029190539052

守护线程(也是线程的一种)

  • setDaemon();如果一个**线程守护线程**,那么它会等待java中其他线程任务结束后,自动终止
  • 守护线程是为其他线程提供服务的,eg:jvm中的垃圾回收机制,就是一个守护线程

多线程

在一个应用程序中,存在多个线程,不同线程可以并行的执行任务

*操作系统线程任务调度算法

  1. 先来先服务调度算法
  2. 短作业优先调度算法
  3. 优先级调度算法
  4. 高响应比优先调度算法
  5. 时间片轮转调度算法
  6. 多级反馈队列调度算法(集合前几种算法的优点)

对线程进行加锁

分析

  • 多线程的优点
    • 提高程序的处理能力
    • 提高CPU的 利用率
  • 缺点
    • 线程也是需要占用内存资源和CPU资源
    • 多个线程对同一个共享资源进行访问,会出现线程安全问题

对于内存资源与CPU资源我们可以通过不断增加内存来解决

对于线程安全问题 我们则需要对 线程进行加锁

synchronized

synchronized 修饰代码块需要加一个同步对象 synchronized(同步对象)

同步对象要求

  • 多线程用到的对象必须是同一个对象
  • 可以是java类中任何类对象.
  • 作用:用来记录有没有线程进入到同步代码块中

修饰方法

  • 锁不需要我们提供,会默认提供锁对象
  • synchronized如果修饰的是非静态方法,锁的对象是this
  • 如果是静态方法,锁的对象是Class的对象 (一个类只能有一个对象)

修饰代码块例子

package day17;public class PrintNums implements Runnable{//实现线程的交替打印int num=100;Object object = new Object();@Overridepublic void run() {while(true){synchronized (object){object.notify();//唤醒线程if(num==0){break;}System.out.println(Thread.currentThread().getName()+"."+num+".");num--;try {object.wait();//线程等待} catch (InterruptedException e) {e.printStackTrace();}}}}
}
package day17;public class TestPrintNums {public static void main(String[] args) {PrintNums printNums = new PrintNums();Thread t1 = new Thread(printNums,"1");Thread t2 = new Thread(printNums,"2");Thread t3 = new Thread(printNums,"3");t1.start();t2.start();t3.start();}
}

image-20231207211850022

于是我们实现了交替打印 每次只能进入一个线程

修饰方法(同步对象会有默认的)

  1. 锁不需要我们提供,会默认提供对象锁
  2. synchronized如果修饰的是非静态方法,锁的对象是this

synchronized如果修饰的是静态方法,锁的对象是类的Class对象,一个类只有 一个对象

  • 如果是非静态方法,那么同步对象是this(如果是非静态对象,我们可以使用Runnable创建线程方法)

  • 如果是静态方法,所得对象是当前类的Class对象

  • 当前类的Class对象:一个类加载到内存后会为这个类创建唯一的Class类的对象

  • Class类实例表示正在运行的Java应用程序中的类和接口

  • 修饰静态方法
    public class SellTicket extends Thread {static int counts = 10;//10张票static Object object = new Object();@Overridepublic void run() {while (counts > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}sellTicket();}}public static synchronized void sellTicket() {if(counts>0){System.out.println(Thread.currentThread().getName()+"买了"+counts+"张票");--counts;}}
    }
    public class Test {public static void main(String[] args) {SellTicket t1 = new SellTicket();t1.setName("窗口1");SellTicket t2 = new SellTicket();t2.setName("窗口2");t1.start();t2.start();}
    }
    

    image-20231209231353289

  • 修饰非静态方法
    public class SellTickets2 implements Runnable{int t=20;//票数@Overridepublic void run() {while(t>0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}sell2();}}public synchronized void sell2(){if(t>0){System.out.println(Thread.currentThread().getName()+"买了"+t+"张票");--t;}}
    }public class Test2 {public static void main(String[] args) {SellTickets2 sellTickets2 = new SellTickets2();Thread t1 = new Thread(sellTickets2,"窗口1");Thread t2 = new Thread(sellTickets2,"窗口2");t1.start();t2.start();}
    }
    

    image-20231209231446179

ReentrantLock类加锁

  • 只能对某一代码块进行加锁,不能对整个方法加锁
  • 加锁方法如下
ReentrantLock r = new ReentrantLock();//创建 ReentrantLock对象
r.lock();<---------|//加锁|.............    |------被锁部分(一次只进去一个线程)|
r.unlock();<-------|//解锁

tips:r.unlock();最好写在finally{};代码块中,保证发生异常时,也能够解锁;

synchronized与ReentrantLock的区别

  1. synchronized是一个关键字,ReentrantLock是一个类

  2. synchronized修饰代码块和方法,ReentrantLock只能修饰代码块

  3. synchronized可以隐式的加锁和释放锁,运行出现异常可以自动释放锁

    ReentrantLock需要手动加锁和释放锁,建议在finally代码中释放锁

常用的三个方法 wait ``notify notifyAll

  • wait();方法使当前线程进入等待状态,直到另一个线程调用该对象的notify()notifyAll()方法来唤醒它

  • notify();方法唤醒在该对象上调用wait()方法进入等待状态的一个线程,如果有多个线程在等待,则只会唤醒其中一个线程。

  • notifyAll();方法唤醒在该对象上调用wait()方法进入等待状态的所有线程。

    tips:1.都是Object类中定义的方法

    ​ 2.三个方法必须在同步代码块中使用

    ​ 3.这三个方法必须通过为锁的对象调用

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

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

相关文章

CleanMyMac X2024免费许可证(激活教程)

CleanMyMac X是一款流行的系统优化工具&#xff0c;专为Mac用户设计。它可以帮助用户清理Mac系统中的垃圾文件、卸载不需要的程序、加速Mac性能以及保护Mac系统的安全。 一、简介 CleanMyMac X是一款功能强大的系统优化工具&#xff0c;它可以帮助用户清理Mac系统中的垃圾文件…

优麒麟ubuntukylin安装UE4.27.2

优麒麟ubuntukylin安装UE4.27.2 在&#xff08;国产&#xff09;优麒麟 ubuntukylin Linux平台上编译测试安装虚幻引擎。 优麒麟系统 这里选择的是官方增强版 https://www.ubuntukylin.com/downloads/ 同样的可以选择对应的Ubuntu22.04 LTS&#xff0c;唯一的区别就是优麒麟…

【精选】SpringMVC简介及其执行流程,参数获取方式

SpringMVC简介 MVC模型 MVC全称Model View Controller&#xff0c;是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中&…

采用NSD评估ADC性能

概要 评估采样器的传统性能指标SNR、SFDR和ENOB最早被用于二战时期,这些性能指标使用于具有通道选择性和低通采样使用的ADC,并不适用于近些年的射频直采ADC,因此需要引入更合适的噪声谱密度NSD(Noise Spectrum Density)指标来评估噪声性能。 传统技术指标的含义 无杂散…

async函数和await表达式

async函数 函数的返回值为promise对象 &#xff08;Promise介绍&#xff09;promise对象的结果由async函数执行的返回值决定&#xff0c;如果对象内返回非promise对象&#xff0c;比如字符串&#xff0c;那么返回结果是成功的promise对象&#xff0c;如果返回的是promise对象&…

Photoshop Circular Text

Ctrl N 新增 现学现卖

uniapp移动端悬浮按钮(吸附边缘)

Uniapp移动端悬浮按钮可以通过CSS实现吸附边缘的效果。具体实现步骤如下&#xff1a; html&#xff1a; <movable-area class"movable-area"><movable-view class"movable-view" :position"position" :x"x" :y"y"…

HarmonyOS4.0从零开始的开发教程06常用基础组件

HarmonyOS&#xff08;四&#xff09;常用基础组件 1 组件介绍 组件&#xff08;Component&#xff09;是界面搭建与显示的最小单位&#xff0c;HarmonyOS ArkUI声明式开发范式为开发者提供了丰富多样的UI组件&#xff0c;我们可以使用这些组件轻松的编写出更加丰富、漂亮的界…

代码随想录-刷题第二十二天

235.二叉搜索树的最近公共祖先 题目链接&#xff1a;235. 二叉搜索树的最近公共祖先 思路&#xff1a;根据二叉搜索树的特性&#xff0c;只需要判断当前节点是否在[p,q]范围内就可以&#xff0c;如果在这个范围里&#xff0c;说明当前节点就是其最近公共祖先。 class Soluti…

C语言进阶之路之结构体、枚举关卡篇

目录 一、学习目标 二、组合数据类型-结构体 结构体基本概念 结构体的声明&#xff1a; 小怪实战 结构体初始化 指定成员初始化的好处&#xff1a; 结构体成员引用 结构体指针与数组 关卡BOOS 三、结构体的尺寸 CPU字长 地址对齐 结构体的M值 可移植性 四、联合体…

Java 使用冒号的七种方式

在 Java 中&#xff0c;冒号字符&#xff08;:&#xff09;用于不同的上下文&#xff0c;并根据上下文的不同而具有不同的含义。 以下是 Java 中冒号的一些常用用法&#xff1a; 1、三元运算符 冒号在三元运算符 (? :) 中用作条件、条件为真时要执行的表达式和条件为假时要执…

计算机视觉 基于Open3D了解用于网格和点云邻域分析的KD树和八叉树

一、简述 距离计算和邻域分析是理解网格和点云的形状、结构和特征的重要工具。我们这里要基于一些3D库来提取基于距离的信息并将其可视化。 与深度图或体素相比,点云和网格表示 3D 空间中的非结构化数据。点由它们的 (X, Y, Z) 坐标表示,在 3D 空间中可能彼此靠近的两…

Python数据科学视频讲解:数据清洗、特征工程和数据可视化的注意事项

1.6 数据清洗、特征工程和数据可视化的注意事项 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.6节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应用的全流程…

深入理解HTTP协议中的GET、POST、DELETE和PUT方法

在Web开发中&#xff0c;我们经常需要与服务器进行交互&#xff0c;以获取或发送数据。为了实现这一目标&#xff0c;我们使用HTTP协议。HTTP协议是一种无状态的、应用层的协议&#xff0c;它定义了客户端和服务器之间的通信方式。在HTTP协议中&#xff0c;有四种常用的请求方法…

MN316 OpenCPU丨HTTP使用介绍

HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;即超文本传输协议&#xff0c;是一个简单的请求-响应协议&#xff0c;通常运行在TCP之上&#xff0c;它指定了客户端可能发送给服务器消息类型以及得到什么类型响应。HTTPS&#xff08;Hyper Text Transfer Protoc…

uniapp使用v-html调用接口,富文本图片 视频自适应大小

前端获取到后台数据 不做处理 就会出现下面问题 图片 视频超出视图显示不全 处理 //info 是富文本 <view v-ifinfo v-htmlreplaceWhite(info)></view>调用下面方法 replaceWhite(html) { // 处理富文本默认图片&#xff0c;视频大小let newContent html.replace…

Nestjs联合Typeorm操作Mysql数据库

创建项目 // 安装脚手架(只需要安装一次,因为这个是全局的) npm i -g nestjs/cli // 创建项目 nest new project-name // (该过程有个选择包管理工具的,我选的yarn)启动项目 yarn run start:dev // 可以在浏览器访问localhost:3000 输出helloWorld安装typeorm,mysql2和nestj…

蓝桥小白赛1

&#x1f469;‍&#x1f3eb; 地址 1. 蘑菇炸弹 &#x1f469;‍&#x1f3eb; 蘑菇炸弹 &#x1f389; AC code import java.util.Scanner;public class Main {public static void main(String[] args){Scanner sc new Scanner(System.in);int n sc.nextInt();int[] a …

d8week17

Week7 lec17 TVD去asscess model &#xff08;本质 距离加权平均&#xff09;text 11.2A New Statistic: The Distance between Two Distributions text-11.11.1 数据拿到手&#xff0c;套路操作 -- 看hist分布2 total variation distance lec18lec19 lec17 TVD去asscess model…

使用NCNN在华为M5部署Yolov5

使用NCNN在华为M5平板部署Yolov5 一、NCNN二、下载解压NCNN三、下载ncnn-android-yolov5工程四、下载Android Studio[前提已经配置了jdk版本]1、安装NDK、Cmske&#xff0c;这个必须要安装&#xff0c;2、安装Android 五、构建工程六、修改源码七、重新ysnc project八、安装APP…