单线程与多线程的理解与学习(入门到深入)

news2024/11/15 4:39:39

在这里插入图片描述

文章目录

      • 一、在Java中,有多种方式可以创建线程。以下是几种常用的方法:
      • 二、线程的调度
        • 线程的调度分为两种调度模型
          • 分时调度模型
          • 抢占式调度模型
      • 三、线程传值
      • 四、什么是线程同步
      • 五、线程安全
      • 六、线程的同步机制
      • 七、线程控制

一、在Java中,有多种方式可以创建线程。以下是几种常用的方法:

  1. 继承Thread类:创建一个继承自Thread类的子类,并重写run()方法,在run()方法中定义线程的执行逻辑。然后通过创建子类对象,调用start()方法来启动线程。示例代码如下:
class MyThread extends Thread {
    public void run() {
        // 线程的执行逻辑
    }
}
// 创建并启动线程
MyThread thread = new MyThread();
thread.start();
  1. 实现Runnable接口:创建一个实现了Runnable接口的类,并实现其run()方法,在run()方法中定义线程的执行逻辑。然后通过创建Runnable实现类的对象,再创建Thread对象,并将Runnable实现类的对象作为参数传递给Thread的构造方法。最后调用Thread对象的start()方法来启动线程。示例代码如下:
class MyRunnable implements Runnable {
    public void run() {
        // 线程的执行逻辑
    }
}
// 创建并启动线程
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
  1. 使用匿名内部类:通过创建匿名内部类来实现Runnable接口,并实现其run()方法。然后创建Thread对象,并将匿名内部类对象作为参数传递给Thread的构造方法。最后调用Thread对象的start()方法来启动线程。示例代码如下:
Runnable runnable = new Runnable() {
    public void run() {
        // 线程的执行逻辑
    }
};
// 创建并启动线程
Thread thread = new Thread(runnable);
thread.start();
  1. 使用线程池:通过Java提供的Executor框架可以方便地创建线程池和管理线程。使用线程池可以更好地控制线程的数量和资源消耗。示例代码如下:
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个固定大小的线程池,最多同时执行5个线程
Runnable runnable = new Runnable() {
    public void run() {
        // 线程的执行逻辑
    }
};
executor.execute(runnable); // 提交任务给线程池执行
executor.shutdown(); // 关闭线程池

以上是几种常见的创建线程的方式,根据具体的需求选择合适的方式来创建线程。注意,在使用多线程时,要注意线程安全和资源共享的问题。

二、线程的调度

假如我们的电脑只有一个CPU,那么CPU在某一时刻只能执行一个指令,其他程序只有分到CPU的时间片(也就是使用权),才能够执行指令。

线程的调度分为两种调度模型

分时调度模型

所有线程轮流使用CPU的使用时间,平均分配每个线程占用CPU的时间片。

抢占式调度模型

优先让优先级的高的线程使用CPU,如果优先级相同,随机选择一个线程,优先级高的线程所获取的CPU时间片会相对多一些。

线程调度是操作系统或者编程语言的任务调度器决定在多个线程之间分配处理器执行时间的过程。线程调度的目标是合理利用CPU资源,提高系统的吞吐量和响应速度。

在Java中,线程调度是由Java虚拟机(JVM)的线程调度器负责的。JVM的线程调度器按照一定的策略来决定哪个线程获得执行时间,具体的调度策略可能因不同的JVM实现而有所不同。

Java线程调度器使用抢占式调度方式。抢占式调度意味着较高优先级的线程可以抢占正在执行的线程的CPU执行时间,以确保高优先级任务的及时执行。线程的优先级用整数表示,范围从1到10,默认为5。可以使用Thread类的setPriority()方法设置线程的优先级。

Java线程调度器基于时间片轮转的调度算法,每个线程被分配一个时间片段,在时间片段结束后,线程调度器会切换到下一个线程继续执行。时间片的长度可以通过操作系统或者JVM的设置进行调整。

除了线程优先级和时间片轮转算法,Java还提供了一些其他的线程调度方法,例如:

  1. yield()方法:调用yield()方法可以让当前线程主动让出CPU执行时间,使得其他具有相同优先级的线程有机会执行。
  2. sleep()方法:调用sleep()方法可以使线程暂停执行一段时间,让其他线程有机会执行。
  3. join()方法:调用join()方法可以让一个线程等待另一个线程执行完毕后再继续执行。
    线程调度是一个复杂的主题,涉及到多个因素,包括线程优先级、时间片分配、同步机制等。了解线程调度的原理和方法,可以帮助开发人员编写高效且可靠的多线程程序。

三、线程传值

在线程之间传递值可以通过以下几种方式实现:

  1. 构造函数或方法参数传递:可以在创建线程的时候,将需要传递的值通过构造函数或者方法参数传递给线程。线程在执行时就可以使用这些传递的值。示例代码如下:
class MyThread extends Thread {
    private int value;
    public MyThread(int value) {
        this.value = value;
    }
    public void run() {
        // 使用传递的值
        System.out.println("Value: " + value);
    }
}
// 创建并启动线程,传递值
int value = 10;
MyThread thread = new MyThread(value);
thread.start();
  1. 实例变量传递:可以在创建线程后,通过设置线程对象的实例变量来传递值。示例代码如下:
class MyThread extends Thread {
    private int value;
    public void setValue(int value) {
        this.value = value;
    }
    public void run() {
        // 使用传递的值
        System.out.println("Value: " + value);
    }
}
// 创建并启动线程,设置实例变量的值
MyThread thread = new MyThread();
int value = 10;
thread.setValue(value);
thread.start();
  1. 使用ThreadLocal:ThreadLocal类可以在每个线程中维护一个变量的副本,每个线程可以独立地访问自己的副本,实现了线程间的数据隔离。示例代码如下:
ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
Runnable runnable = new Runnable() {
    public void run() {
        // 设置线程的变量值
        threadLocal.set(10);
        // 获取线程的变量值
        System.out.println("Value: " + threadLocal.get());
        // 清除线程的变量值
        threadLocal.remove();
    }
};
// 创建并启动线程
Thread thread = new Thread(runnable);
thread.start();

通过上述方法,可以在不同的线程间传递值,并在线程内部获取和使用这些传递的值。注意在多线程场景下,要注意线程安全和数据一致性的问题。

四、什么是线程同步

线程同步是一种机制,用于协调多个线程之间的执行顺序和共享资源的访问,以避免出现数据不一致或不确定的结果。
在多线程环境下,如果多个线程同时访问和修改共享资源,可能会导致以下问题:

  1. 竞态条件(Race Condition):多个线程同时访问和修改同一个共享变量,导致最终结果的不确定性。
  2. 数据不一致(Data Inconsistency):多个线程对共享数据进行操作,其中一个线程的操作可能会影响到其他线程的操作,导致数据的不一致性。
    线程同步的目的是通过限制多个线程的执行顺序,并提供互斥访问共享资源的机制,确保线程之间的协调和数据的一致性。
    常见的线程同步机制包括:
  3. 锁机制:使用锁(如synchronized关键字和ReentrantLock类)来保护共享资源的访问,确保同一时刻只有一个线程可以访问共享资源,从而避免竞态条件和数据不一致。
  4. 条件变量:使用条件变量(如wait()、notify()、notifyAll())来实现线程之间的等待和唤醒机制,以实现有序访问和协作。
  5. 原子操作:使用原子类(如AtomicInteger、AtomicReference等)来实现对共享变量的原子操作,保证操作的原子性,避免竞态条件和数据不一致。
  6. volatile关键字:使用volatile关键字来保证共享变量的可见性,确保多个线程对变量进行操作时能够看到最新的值。
    线程同步的实现方式取决于具体的需求和场景。需要根据情况选择合适的同步机制,并进行必要的测试和验证,以确保线程的安全和数据的一致性。同时,也需要注意避免死锁、活锁等问题,以保证程序的正常执行。

五、线程安全

线程安全是指在多线程环境下,对共享资源的访问操作能够正确、可靠地执行,不会出现数据不一致或不确定的结果。
在多线程编程中,线程安全是一个重要的概念,需要特别注意以下几个方面:

  1. 原子性(Atomicity): 原子操作是指一个操作是不可中断的,要么全部执行成功,要么全部不执行。例如,对于一个整型变量的自增操作,如果不是线程安全的,可能会出现多个线程同时读取并修改值,导致结果不正确。可以使用原子类(Atomic classes)或加锁(synchronized、Lock)来保证原子操作。
  2. 可见性(Visibility): 可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到该变化。使用volatile关键字可以保证变量的可见性。此外,使用synchronized或Lock机制也可以确保线程间的可见性。
  3. 有序性(Ordering): 有序性是指程序按照一定的顺序来执行。在多线程环境下,由于线程的调度和指令重排等因素,可能会导致程序执行顺序的不确定性。可以使用volatile关键字或同步机制来保证指令的有序性。
  4. 线程安全的数据结构和类:Java提供了一些线程安全的数据结构和类,如ConcurrentHashMap、CopyOnWriteArrayList等,它们在多线程环境下能够安全地进行操作,并且不需要额外的同步。
    要保证线程安全,可以采取以下几种方式:
  • 使用线程安全的数据结构和类。
  • 使用锁(synchronized、Lock)来保护共享资源的访问。
  • 使用volatile关键字来保证变量的可见性。
  • 避免使用可变的共享对象,尽量使用不可变对象。
  • 合理设计线程安全的算法和逻辑。
    需要根据具体的场景和需求选择合适的线程安全解决方案,并进行必要的测试和验证,以确保程序在多线程环境下的正确性和稳定性。

六、线程的同步机制

线程的同步机制是一种用于控制多个线程之间访问共享资源的机制,确保线程之间的正确交互和数据一致性。常见的线程同步机制包括:

  1. synchronized关键字:synchronized关键字可以用于方法和代码块。当一个线程进入synchronized修饰的方法或代码块时,它会获得对象的锁,其他试图获取锁的线程将被阻塞,直到该线程释放锁。synchronized关键字确保了同一时刻只有一个线程可以访问被锁定的代码,从而保证了线程的安全性。
    示例代码:
public synchronized void synchronizedMethod() {
    // 同步方法
}
public void method() {
    synchronized (this) {
        // 同步代码块
    }
}
  1. ReentrantLock类:ReentrantLock是Java提供的一个可重入锁,它提供了更多的灵活性和功能。与synchronized不同,ReentrantLock需要手动地进行加锁和释放锁的操作,可以更灵活地控制锁的获取和释放。它还提供了可定时的、可中断的锁等功能,使得线程同步更加灵活。
    示例代码:
ReentrantLock lock = new ReentrantLock();
public void method() {
    lock.lock();
    try {
        // 同步代码
    } finally {
        lock.unlock();
    }
}
  1. volatile关键字:volatile关键字用于修饰共享变量,保证了变量的可见性。当一个线程修改了volatile变量的值,其他线程可以立即看到该变化。然而,volatile关键字无法保证复合操作的原子性,也无法解决竞态条件问题。
    示例代码:
private volatile int sharedVariable;
public void method() {
    // 修改共享变量
    sharedVariable = 10;
    // 读取共享变量
    int value = sharedVariable;
}
  1. wait()和notify()/notifyAll()方法:wait()方法用于线程间的等待,notify()和notifyAll()方法用于线程间的唤醒。这些方法通常与synchronized关键字一起使用,用于实现线程间的协作和同步。通过wait()方法,线程可以主动释放对象的锁,并进入等待状态,直到其他线程调用notify()或notifyAll()方法来唤醒它。
    示例代码:
Object lock = new Object();
public void producer() throws InterruptedException {
    synchronized (lock) {
        // 生产数据
        lock.notify(); // 唤醒消费者线程
    }
}
public void consumer() throws InterruptedException {
    synchronized (lock) {
        lock.wait(); // 等待生产者线程唤醒
        // 消费数据
    }
}

这些线程同步机制可以根据具体的需求和场景进行选择和使用,确保线程之间的正确交互和共享资源的安全访问。同时,也需要注意避免死锁、竞态条件等问题,以确保线程的正常执行。

七、线程控制

在这里插入图片描述

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

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

相关文章

惠普HP Color Laser 150a开机红色感叹号闪烁不打印故障解决方法

故障描述&#xff1a; 惠普HP Color Laser 150a开机红色感叹号闪烁&#xff0c;不能打印&#xff0c;电脑提示C3-6140。 检测分析&#xff1a; 在解决C3-6140错误代码之前&#xff0c;我们需要先检查打印机是否连接正常。如果打印机连接不正常&#xff0c;也可能会出现这个错误…

mysql_2.4——安装常见问题

1. 将MySQL添加到环境变量 将 mysql 的 bin 目录地址添加到 系统环境变量 --> PATH 中 2. 将MySQL添加到服务 以管理员的方式启动 cmd (命令提示窗口)&#xff0c;使用命令进入到 [mysql]\bin &#xff0c;执行如下命 令。 # mysqld --install (服务名) # 如: mysqld --…

SQL注入实操Less21-30)

文章目录 一、sqli-lab靶场1.轮子模式总结2.Less-21a.注入点判断b.轮子测试c.获取数据库名称d.获取表信息e.获取列信息f.获取表内数据 3.Less-22a.注入点判断b.轮子测试c.获取数据库名称d.获取表信息e.获取列信息f.获取表内数据 4.Less-23a.注入点判断b.轮子测试c.获取数据库名…

questasim界面的个性化设置

安装好questasim后默认的波形查看界面字体很小&#xff0c;颜色看起来也不舒服&#xff0c;所以调整了一下颜色布局如下图&#xff0c;顺便记录一下波形窗口颜色大小及选中行高亮如何设置 ​​​​​​​ 1、波形字体颜色设置 参考如何设置一个清爽的仿真窗口&#xff08;仿真…

【无标题】linux就该这么学

linux就该这么学 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚…

杰哥教你用Python对Emotet投递的恶意Excel表格提取IoCs

背景介绍 工作遇到多个经过同样方式混淆并隐藏的宏代码文档&#xff0c;利用Excel表格特性&#xff0c;将数据分离在不同的单元格中&#xff0c;再使用Office自带的函数对单元格的数值进行提取后组合成代码字符串运行。运行的代码完成下载恶意文件到本地并注册为服务的恶意行为…

spring项目中idea提示Application context not configured for this file

今天在重构项目的时候&#xff0c;碰到一个问题。就是在spring底下&#xff0c;有一个包里面的所有配置类&#xff0c;在idea的开发工具类底下提示&#xff0c;Application context not configured for this file&#xff0c;如图所示 一开始以为是警告&#xff0c;不予处理&am…

04 linux之C 语言高级编程

gcc和gdb GNU工具 编译工具&#xff1a;把一个源程序编译为一个可执行程序调试工具&#xff1a;能对执行程序进行源码或汇编级调试软件工程工具&#xff1a;用于协助多人开发或大型软件项目的管理&#xff0c;如make、CVS、Subvision其他工具&#xff1a;用于把多个目标文件链…

《入门级-Cocos2d 4.0塔防游戏开发》---第二课:游戏加载界面开发

一、开发环境介绍 操作系统&#xff1a;UOS1060专业版本。 cocos2dx:版本 环境搭建教程&#xff1a; 统信UOS下配置安装cocos2dx开发环境_三雷科技的博客-CSDN博客 二、开发内容 游戏在开始时都需要加载大量的资源&#xff0c;为了让用户有等待时间&#xff0c;因此最先开…

linux学成之路(基础篇)(二十三)MySQL服务(数据库备份——补充)

目录 一、MySQL数据库备份 概述 重要性 造成数据丢失的原因 二、备份类型 一、物理与逻辑角度 一、物理备份 二、逻辑备份 二、数据库备份策略角度 一、完整备份 二、增量备份 三、常见的备份方法 一、物理备份 二、使用专用备份工具 三、通过启用二进制日志增量…

漏洞发现-Xray+Awvs联动-Goby+Xray+Awvs+Vulmap联动

Acunetix: Acunetix一款商业的Web漏洞扫描程序&#xff0c;它可以检查Web应用程序中的漏洞&#xff0c;如SQL注入、跨站脚本攻击、身份验证页上的弱口令长度等。它拥有一个操作方便的图形用户界面&#xff0c;并且能够创建专业级的Web站点安全审核报告。新版本集成了漏洞管理功…

在家构建您的迷你 ChatGPT

这篇文章分为三个部分&#xff1b;他们是&#xff1a; 什么是指令遵循模型&#xff1f;如何查找遵循模型的指令构建一个简单的聊天机器人废话不多说直接开始吧&#xff01;&#xff01;&#xff01; 什么是指令遵循模型&#xff1f; 语言模型是机器学习模型&#xff0c;可以根…

移动开发之Wifi列表获取功能

一、场景 业务需要通过App给设备配置无线网络连接&#xff0c;所以需要App获取附近的WiFi列表&#xff0c;并进行网络连接验证。 二、安卓端实现 1、阅读谷歌官网文档&#xff0c;关于Wifi 接口使用 https://developer.android.com/guide/topics/connectivity/wifi-scan?hl…

SpringBoot——内置数据库

简单介绍 关于数据层的三大组件&#xff0c;数据源&#xff0c;持久化技术&#xff0c;数据库。前两种都已经介绍过了SpringBoot的内置的解决方案&#xff0c;还有最后一个数据库&#xff0c;在SpringBoot中&#xff0c;内置了三款数据库。分别是&#xff1a; H2HSQLDerby 这…

ARTIF:一种先进的实时威胁智能识别框架

关于ARTIF ARTIF是一个新型的高级实时威胁智能框架&#xff0c;它基于MISP并添加了另一个抽象层&#xff0c;以实现根据IP地址和历史数据识别恶意Web流量。除此之外&#xff0c;该工具还可以通过收集、处理和关联基于不同因素的观测值来执行自动分析和威胁评分。 功能介绍 评…

uni-app在小米手机上运行【步骤细节】

注意细节重点&#xff1a; 1.手机使用数据线与电脑连接&#xff0c;手机连接模式必须是传输文件模式 2.手机必须打开开发者模式 3.打开开发者模式后&#xff0c;仔细浏览并调整USB调试权限&#xff0c;重点打开USB是否允许安装按钮&#xff01;&#xff01;&#xff01; 操作步…

onnxruntime (C++/CUDA) 编译安装

一、克隆及编译 git clone --recursive https://github.com/Microsoft/onnxruntime cd onnxruntime/ git checkout v1.8.0如果克隆的时候报错&#xff1a; 执行以下&#xff1a; apt-get install gnutls-bin git config --global http.sslVerify false git config --global h…

自动化测试的技术路线

本文中我谈一下自动化测试的技术路线&#xff0c;同时也是测试团队的发展路线。 团队路线1.工程化路线 如果你们公司只有你一个测试&#xff0c;那工程化的路线是必然的选择。另外&#xff0c;我个人比较推崇工程化而非平台化。 下图介绍了工程化路线下写出来的自动化测试&…

[oeasy]python0075_删除变量_del_delete_variable

删除变量 回忆上次内容 上次我们研究了字节序 字节序有两种 符号英文名称中文名称<little-endian小字节序>big-endian大字节序 字节序 用来 明确 整型数字存储的 顺序 如果 读写数字出了错 可以 考虑一下 是否 字节序出了问题 变量现在可以 声明初始化存储了 但是 …

Animator Animator Controller Avatar relationship

Animator 组件用于将动画分配给场景中的游戏对象。Animator 需要对Animator Controller 的引用&#xff0c;该控制器定义要使用的动画剪辑&#xff0c;并控制何时以及如何在它们之间混合和过渡。 如果 GameObject 是具有 Avatar 定义的人形角色&#xff0c;则 Avatar 也应在此组…