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.hqwc.cn/news/263056.html

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

相关文章

uniapp实战 —— 分类导航【详解】

效果预览 组件封装 src\pages\index\components\CategoryPanel.vue <script setup lang"ts"> import type { CategoryItem } from /types/index defineProps<{list: CategoryItem[] }>() </script><template><view class"category&…

法律服务网站建设效果如何

律师事务所及法律知识咨询机构等往往是众多人群需求的服务&#xff0c;服务多样化及内容多元化&#xff0c;市场中也有大量品牌&#xff0c;在实际消费服务中大多以本地事务所为主&#xff0c;而线上咨询服务则一般没有区域限制&#xff0c;同行增多及人们知识获取渠道增加&…

Flutter笔记:滑块及其实现分析1

Flutter笔记 滑块分析1 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134900784 本文从设计角度&#…

【计算机网络实验】实验三 IP网络规划与路由设计(头歌)

目录 一、知识点 二、实验任务 三、头歌测试 一、知识点 IP子网掩码的两种表示方法 32位IP子网掩码&#xff0c;特点是从高位开始连续都是1&#xff0c;后面是连续的0&#xff0c;它有以下两种表示方法&#xff1a; 传统表示法&#xff0c;如&#xff1a;255.255.255.0IP前…

Mybatis中的查询操作

单表查询 单表查询在《初始Mybatis》中已经介绍过&#xff0c;这里就不在介绍了。咱们这里只说单表查询中的“like查询”。like查询单独使用#{}报错 <select id"selectByKeyword" resultType"com.example.demo.entity.Userinfo">select * from use…

飞天使-linux操作的一些技巧与知识点4

文章目录 ansible配置文件的优先级尝试开始进行操作ansible常用模块ansible 的playbook示例安装phpplaybook中变量的引用 ansible yum install -y ansible 测试是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…

JS基础之原型原型链

JS基础之原型&原型链 原型&原型链构造函数创建对象prototypeprotoconstructor实例与原型原型的原型原型链其他constructorproto继承 原型&原型链 构造函数创建对象 我们先使用构造函数创建一个对象&#xff1a; function Person(){ } var person new Person();…

Notes数据直接在Excel中统计

大家好&#xff0c;才是真的好。 我希望你看过前面两篇内容《Domino REST API安装和运行》和《Domino REST API安装和运行》&#xff0c;因为今天我们正是使用REST API方式在Excel中查询和统计Notes数据。 不过首先你得知道一个OData协议&#xff0c;全名Open Data Protocol(…

mips平台运行valgrind无法统计到内存泄漏

目录 前言&#xff1a; 问题分析过程&#xff1a; 解决方案&#xff1a; 说明&#xff1a; 前言&#xff1a; mips的板子上&#xff0c;运行了linux系统和应用程序&#xff08;本公司业务程序&#xff09;&#xff0c;经过长时间观察&#xff0c;发现应用程序存在内存泄漏…

nginx配置正向代理支持https

操作系统版本&#xff1a; Alibaba Cloud Linux 3.2104 LTS 64位 nginx版本&#xff1a; nginx-1.25.3 1. 下载软件 切换目录 cd /server wget http://nginx.org/download/nginx-1.25.3.tar.gz 1.1解压 tar -zxvf nginx-1.25.3.tar.gz 1.2切换到源码所在目录…

基于Python+WaveNet+MFCC+Tensorflow智能方言分类—深度学习算法应用(含全部工程源码)(四)

目录 前言引言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 模型构建3. 模型训练及保存4. 模型生成 系统测试1. 训练准确率2. 测试效果 相关其它博客工程源代码下载其它资料下载 前言 博主前段时间发布了一篇有关方言识别和分类模型训练的博客&#xff…

TruLens RAG Triad 学习

TruLens RAG Triad 学习 0. 背景1. RAG 三元组2. TruLens 快速入门2-1. 安装依赖2-2. 初始化 OpenAI 认证信息2-3. 获取数据2-4. 创建向量存储2-5. 从头构建自定义 RAG2-6. 设置反馈函数2-7. 构建应用程序2-8. 运行应用程序0. 背景 近年来,RAG 架构已成为为大型语言模型 (LLM…