当前位置: 首页 > news >正文

多线程(一)

1.1简单了解多线程【理解】

是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能。

1.2并发和并行【理解】

并行:在同一时刻,有多个指令在多个CPU上同时执行。

并行:在同一时刻,有多个指令在多个CPU上同时执行。

1.3进程和线程【理解】

  • 进程:是正在运行的程序

    独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位 动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的 并发性:任何进程都可以同其他进程一起并发执行

  • 线程:是进程中的单个顺序控制流,是一条执行路径

    单线程:一个进程如果只有一条执行路径,则称为单线程程序

    多线程:一个进程如果有多条执行路径,则称为多线程程序

1.4实现多线程方式一:继承Thread类【应用】

  • 方法介绍

    方法名说明
    void run()在线程开启后,此方法将被调用执行
    void start()使此线程开始执行,Java虚拟机会调用run方法()
  • 实现步骤

    • 定义一个类MyThread继承Thread类

    • 在MyThread类中重写run()方法

    • 创建MyThread类的对象

    • 启动线程

代码演示

public class MyThread extends Thread { @Override public void run() { for(int i=0; i<100; i++) { System.out.println(i); } } } public class MyThreadDemo { public static void main(String[] args) { MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); // my1.run(); // my2.run(); //void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法 my1.start(); my2.start(); } }
  • 两个小问题

    • 为什么要重写run()方法?

      因为run()是用来封装被线程执行的代码

    • run()方法和start()方法的区别?

      run():封装线程执行的代码,直接调用,相当于普通方法的调用

      start():启动线程;然后由JVM调用此线程的run()方法

1.5实现多线程方式二:实现Runnable接口【应用】

  • Thread构造方法

    方法名说明
    Thread(Runnable target)分配一个新的Thread对象
    Thread(Runnable target, String name)分配一个新的Thread对象
  • 实现步骤

    • 定义一个类MyRunnable实现Runnable接口

    • 在MyRunnable类中重写run()方法

    • 创建MyRunnable类的对象

    • 创建Thread类的对象,把MyRunnable对象作为构造方法的参数

    • 启动线程

  • 代码演示

public class MyRunnable implements Runnable { @Override public void run() { for(int i=0; i<100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } public class MyRunnableDemo { public static void main(String[] args) { //创建MyRunnable类的对象 MyRunnable my = new MyRunnable(); //创建Thread类的对象,把MyRunnable对象作为构造方法的参数 //Thread(Runnable target) // Thread t1 = new Thread(my); // Thread t2 = new Thread(my); //Thread(Runnable target, String name) Thread t1 = new Thread(my,"坦克"); Thread t2 = new Thread(my,"飞机"); //启动线程 t1.start(); t2.start(); } }

1.6实现多线程方式三: 实现Callable接口【应用】

  • 方法介绍

    方法名说明
    V call()计算结果,如果无法计算结果,则抛出一个异常
    FutureTask(Callable<V> callable)创建一个 FutureTask,一旦运行就执行给定的 Callable
    V get()如有必要,等待计算完成,然后获取其结果
  • 实现步骤

    • 定义一个类MyCallable实现Callable接口

    • 在MyCallable类中重写call()方法

    • 创建MyCallable类的对象

    • 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数

    • 创建Thread类的对象,把FutureTask对象作为构造方法的参数

    • 启动线程

    • 再调用get方法,就可以获取线程结束之后的结果。

  • 代码演示

public class MyCallable implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println("跟女孩表白" + i); } //返回值就表示线程运行完毕之后的结果 return "答应"; } } public class Demo { public static void main(String[] args) throws ExecutionException, InterruptedException { //线程开启之后需要执行里面的call方法 MyCallable mc = new MyCallable(); //Thread t1 = new Thread(mc); //可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象 FutureTask<String> ft = new FutureTask<>(mc); //创建线程对象 Thread t1 = new Thread(ft); String s = ft.get(); //开启线程 t1.start(); //String s = ft.get(); System.out.println(s); } }
  • 三种实现方式的对比

    • 实现Runnable、Callable接口

      • 好处: 扩展性强,实现该接口的同时还可以继承其他的类

      • 缺点: 编程相对复杂,不能直接使用Thread类中的方法

    • 继承Thread类

      • 好处: 编程比较简单,可以直接使用Thread类中的方法

      • 缺点: 可以扩展性较差,不能再继承其他的类

1.7设置和获取线程名称【应用】

  • 方法介绍

    方法名说明
    void setName(String name)将此线程的名称更改为等于参数name
    String getName()返回此线程的名称
    Thread currentThread()返回对当前正在执行的线程对象的引用
  • 代码演示

public class MyThread extends Thread { public MyThread() {} public MyThread(String name) { super(name); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName()+":"+i); } } } public class MyThreadDemo { public static void main(String[] args) { MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //void setName(String name):将此线程的名称更改为等于参数 name my1.setName("高铁"); my2.setName("飞机"); //Thread(String name) MyThread my1 = new MyThread("高铁"); MyThread my2 = new MyThread("飞机"); my1.start(); my2.start(); //static Thread currentThread() 返回对当前正在执行的线程对象的引用 System.out.println(Thread.currentThread().getName()); } }

1.8线程休眠【应用】

  • 相关方法

    方法名说明
    static void sleep(long millis)使当前正在执行的线程停留(暂停执行)指定的毫秒数
  • 代码演示

public class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "---" + i); } } } public class Demo { public static void main(String[] args) throws InterruptedException { /*System.out.println("睡觉前"); Thread.sleep(3000); System.out.println("睡醒了");*/ MyRunnable mr = new MyRunnable(); Thread t1 = new Thread(mr); Thread t2 = new Thread(mr); t1.start(); t2.start(); } }

1.9线程优先级【应用】

  • 线程调度

    • 两种调度方式

      • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

      • 抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

    • Java使用的是抢占式调度模型

    • 随机性

      假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的

  • 优先级相关方法

    方法名说明
    final int getPriority()返回此线程的优先级
    final void setPriority(int newPriority)更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10
  • 代码演示

public class MyCallable implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "---" + i); } return "线程执行完毕了"; } } public class Demo { public static void main(String[] args) { //优先级: 1 - 10 默认值:5 MyCallable mc = new MyCallable(); FutureTask<String> ft = new FutureTask<>(mc); Thread t1 = new Thread(ft); t1.setName("飞机"); t1.setPriority(10); //System.out.println(t1.getPriority());//5 t1.start(); MyCallable mc2 = new MyCallable(); FutureTask<String> ft2 = new FutureTask<>(mc2); Thread t2 = new Thread(ft2); t2.setName("坦克"); t2.setPriority(1); //System.out.println(t2.getPriority());//5 t2.start(); } }

1.10守护线程【应用】

  • 相关方法

    方法名说明
    void setDaemon(boolean on)将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
  • 代码演示

public class MyThread1 extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName() + "---" + i); } } } public class MyThread2 extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName() + "---" + i); } } } public class Demo { public static void main(String[] args) { MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.setName("女神"); t2.setName("备胎"); //把第二个线程设置为守护线程 //当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了. t2.setDaemon(true); t1.start(); t2.start(); } }
http://www.jsqmd.com/news/201757/

相关文章:

  • 10分钟用MC.JS 1.8.8验证你的Minecraft创意
  • 新品发布会筹备:GLM-4.6V-Flash-WEB模拟媒体关注点与提问方向
  • 在FPGA开发板上运行自定义ALU:零基础指南
  • OLLAMA下载指南:AI如何简化本地大模型部署
  • XXL-JOB与AI结合:智能调度任务的新时代
  • 企业级数据仓库实战:KETTLE下载与ETL最佳实践
  • 金融科技企业利用GLM-4.6V-Flash-WEB提升反欺诈图像分析效率
  • 基于74LS系列芯片的时序逻辑电路设计实验教程
  • 从开源模型到生产级应用:我们提供的GLM-4.6V-Flash-WEB全栈支持
  • 环保监测摄像头画面理解:GLM-4.6V-Flash-WEB发现违规排污行为
  • 食品营养标签读取:GLM-4.6V-Flash-WEB生成饮食建议
  • GLM-4.6V-Flash-WEB对模糊、低清图像的容忍度测试结果
  • 品牌舆情监控:GLM-4.6V-Flash-WEB发现负面图像传播源头
  • YARN vs 传统调度器:效率对比分析
  • 5分钟快速搭建TOMCAT开发环境原型
  • HEIDISQL在企业级数据库管理中的5个实战案例
  • YOLO26 vs 传统CV:效率提升对比实测
  • 播客节目配图生成:GLM-4.6V-Flash-WEB根据音频内容建议插画
  • Elasticsearch零基础入门:从安装到第一个查询
  • 自动售货机界面适老化改造:GLM-4.6V-Flash-WEB语音引导操作
  • 零基础教程:用快马制作你的第一个HTML圣诞树
  • 升级 .NET 10 前,先看看这几个你一定会用上的新能力
  • 外卖平台菜品图片审核:GLM-4.6V-Flash-WEB过滤虚假宣传内容
  • Yocto定制Linux内核:从配置到编译完整指南
  • USB3.0终端阻抗匹配设计:手把手教程(零基础适用)
  • 机场值机柜台辅助:GLM-4.6V-Flash-WEB识别护照与行李标签
  • 零基础理解排列组合:CN和AN公式图解教程
  • 用ZABBIX快速搭建物联网设备监控原型
  • 工业控制中vivado安装教程2018的深度剖析
  • 【2025年终盘点】.NET 10 封神之年:从后台大叔到AI先锋的华丽转身,2026年你还等什么?