【线程创建】——三种方式➕多线程案例练习

02 线程创建

Thread , Runnable , Callable

三种创建方式

Thread class - 继承Thread类 (重点)

Runnable接口 - 实现Runnable接口 (重点)

Callable接口 - 实现Callable接口 (了解)

Thread 类实现

它继承了老祖宗 Object
java.lang.Object
java.lang.Thread

它实现了 Runnable接口

线程是程序中执行的线程. Java虚拟机允许应用程序同时执行多个执行线程.

每个线程都有优先权. 就是你的优先权更高你先执行, 你的优先权低你就后执行, 还有守护线程, 和用户线程, 这个地方先不聊, 本章主要讲如何创建线程

创建一个新的线程有两种方法, 一个是将一个类声明为Thread的子类, 这个子类应该重新run类的方法Thread. 然后可以分配并启动子类的实例. 例如, 计算大于规定值的素数的线程可以写成如下:

  • 自定义线程类继承**Thread类**
  • 重写**run()**方法
  • 创建线程对象, 调用**start()**方法启动线程
继承Thread类实现

我们下面用代码实现一下:

package com.jean.thread;

//创建线程方式一: 继承Thread类, 重写run()方法, 调用start开启线程
public class TestThread1 extends Thread {

//    继承完, 立即重写run方法
    @Override
    public void run() {
//        run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码----"+i);
        }
    }

    public static void main(String[] args) {
//        main线程, 主线程
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程----"+i);
        }
    }
}

我们执行后, 控制台加载完后就一瞬间输出了20个我在学习多线程, 我们如果想把另一个线程开启怎么开呢?

package com.jean.thread;

//创建线程方式一: 继承Thread类, 重写run()方法, 调用start开启线程
public class TestThread1 extends Thread {

//    继承完, 立即重写run方法
    @Override
    public void run() {
//        run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码----"+i);
        }
    }

    public static void main(String[] args) {
//        main线程, 主线程

//        首先创建它的一个对象
        TestThread1 testThread1 = new TestThread1();
//        调用start方法, 开启线程
        testThread1.start();


        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程----"+i);
        }
    }
}

在这里插入图片描述

我们调用了start方法后, 控制台明显执行的先后顺序就随机了, 所以说

调用start()方法是同时来运行的, 交替执行

我们的多线程调用了一个start方法, 它直接走下来进了start方法, 他开辟了一条新的线程, 它去执行它的方法, 主线程依据去走主线程的

然后我们再改调用run()方法

package com.jean.thread;

//创建线程方式一: 继承Thread类, 重写run()方法, 调用start开启线程
public class TestThread1 extends Thread {

//    继承完, 立即重写run方法
    @Override
    public void run() {
//        run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码----"+i);
        }
    }

    public static void main(String[] args) {
//        main线程, 主线程

//        首先创建它的一个对象
        TestThread1 testThread1 = new TestThread1();
//        调用run方法, 开启线程
        testThread1.run();


        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程----"+i);
        }
    }
}

在这里插入图片描述
使用run方法调用, 他先走run方法, 执行完了才去执行主路径

总结:

线程开启不一定立即执行, 由CPU调度安排

多线程网图下载

案例: 下载图片

使用多线程同时去下载几个图片

  1. 先引入一下jar包 Commons IO包.

可以直接去百度搜索Commons IO , 是Apache下的.

  • Commons IO是针对开发IO流功能的工具类库.

  • FileUtils文件工具, 复制url到文件

Commons-io包的下载地址
在这里插入图片描述
点击图中红色圈起来的jar链接即可实现下载

创建lib文件, 把lib目录添加为库.

  1. 创建lib文件
  2. 点击lib文件获取焦点, 右键点击
  3. 选择添加为库
  4. 添加为jar
    在这里插入图片描述
    添加成功之后, 文件前会有一个箭头

新建TestDownload文件

package com.jean.thread;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

/**
 * @BelongsProject: Thread-class01
 * @BelongsPackage: com.jean.thread
 * @Author: Jean_z
 * @CreateTime: 2024-05-13  08:31
 * @Description: TODO: 练习Thread, 实现多线程同步下载图片
 * @Version: 1.0
 */
public class TestDownload implements Runnable{

    private String url; //网络图片地址
    private String name; //保存的文件名

//    构造器
    public TestDownload(String url, String name) {
        this.url = url;
        this.name = name;
    }

//    下载图片线程的执行体
    @Override
    public void run() {
        WebDownload webDownload = new WebDownload();
        webDownload.download(url,name);
        System.out.println("下载了文件名为:" + name);
    }

//    启动线程
    public static void main(String[] args) {
        TestDownload testDownload1 = new TestDownload("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字1");
        TestDownload testDownload2 = new TestDownload("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字2");
        TestDownload testDownload3 = new TestDownload("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字3");

//        Thread类方法
//        testDownload1.start();
//        testDownload2.start();
//        testDownload3.start();

//        Runnable接口方法
        new Thread(testDownload1).start();
        new Thread(testDownload2).start();
        new Thread(testDownload3).start();
    }
}

// 下载器
class WebDownload {
//    下载方法
    public void download(String url,String name) {
//        FileUtils: 文件工具
//        copyURLToFile 拷贝url地址到一个文件
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, download 方法出问题了");
        }
    }
}

Runnable接口实现多线程.

跟推荐的一种实现多线程的方式: Runnable

创建线程方式2

  1. 实现Runnable接口,
  2. 重写run方法, 执行线程需要丢入runnable接口实现类,调用start方法.
package com.jean.thread;

/**
 * @BelongsProject: Thread-class01
 * @BelongsPackage: com.jean.thread
 * @Author: Jean_z
 * @CreateTime: 2024-05-13  09:38
 * @Description: TODO
 * @Version: 1.0
 */

//创建线程方式2 : 实现Runnable接口, 重写run方法, 执行线程需要丢入runnable接口实现类,调用start方法.
public class TestRunnable implements Runnable{
    //    继承完, 立即重写run方法
    @Override
    public void run() {
//        run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码----"+i);
        }
    }

    public static void main(String[] args) {
//        main线程, 主线程
//        创建runnable接口的实现对象
        TestRunnable runnable = new TestRunnable();

//        创建线程对象, 通过线程对象来开启我们的线程, 代理
//        Thread thread = new Thread(runnable);
//        调用start方法, 开启线程
        new Thread(runnable).start();


        for (int i = 0; i < 2000; i++) {
            System.out.println("我在学习多线程----"+i);
        }
    }
}

Callable 方式 实现多线程

第三种实现多线程的方式: Callable

我们基于多线程下载网络图片代码, 修改.

  1. 实现Callable接口

  2. 重写call方法 类型

  3. 创建执行事务

    ExecutorService executorService = Executors.newFixedThreadPool (3);

  4. 提交执行

  5. 获取执行结果, boolean类型

  6. 关闭服务

之前是重写run方法, 我们这里不一样, 重写的是call方法, 注意方法类型是布尔.

第三种方式, 了解即可 !

package com.jean.thread;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

/**
 * @BelongsProject: Thread-class01
 * @BelongsPackage: com.jean.thread
 * @Author: Jean_z
 * @CreateTime: 2024-05-13  08:31
 * @Description: TODO: 练习Thread, 实现多线程同步下载图片
 * @Version: 1.0
 */
public class TestCallable implements Callable<Boolean> {

    private String url; //网络图片地址
    private String name; //保存的文件名

//    构造器
    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }

//    下载图片线程的执行体
    @Override
    public Boolean call() {
        WebDownload2 webDownload = new WebDownload2();
        webDownload.download(url,name);
        System.out.println("下载了文件名为:" + name);
        return true;
    }

//    启动线程
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable testCallable1= new TestCallable("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字1");
        TestCallable testCallable2= new TestCallable("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字2");
        TestCallable testCallable3= new TestCallable("https://img-home.csdnimg.cn/images/20240511083237.png", "我是图片的名字3");

//        Thread类方法
//        testDownload1.start();
//        testDownload2.start();
//        testDownload3.start();

//        创建执行事务
        ExecutorService executorService = Executors.newFixedThreadPool(3);


//        提交执行
        Future<Boolean> r1 = executorService.submit(testCallable1);
        Future<Boolean> r2 = executorService.submit(testCallable2);
        Future<Boolean> r3 = executorService.submit(testCallable3);

//        获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();

        System.out.println(rs1);
        System.out.println(rs2);
        System.out.println(rs3);

//        关闭服务
        executorService.shutdownNow();
    }
}

// 下载器
class WebDownload2 {
//    下载方法
    public void download(String url,String name) {
//        FileUtils: 文件工具
//        copyURLToFile 拷贝url地址到一个文件
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, download 方法出问题了");
        }
    }
}

多线程 “龟🐢” “兔🐇” 赛跑案例

案例需求:

  1. 首先先来个赛道距离, 然后要离重点越来越近
  2. 判断比赛是否结束
  3. 打印出胜利者
  4. 龟兔赛跑开始
  5. 故事中是乌龟🐢速度慢但是依旧是乌龟赢的, 兔子🐇需要睡觉, 所以我们来模拟兔子睡觉💤
  6. 终于, 乌龟🐢赢得比赛.
sleep多线程的延时方法

Thread.sleep ( 5000 ) // 这里是毫秒

package com.jean.thread;

/**
 * @BelongsProject: Thread-class01
 * @BelongsPackage: com.jean.thread
 * @Author: Jean_z
 * @CreateTime: 2024-05-13  10:21
 * @Description: TODO
 * @Version: 1.0
 */
//模拟龟兔赛跑
public class TestRace implements Runnable{

//    胜利者
    private static String winner;
//    private static String winner;

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {

//            模拟兔子休息
            if (Thread.currentThread().getName().equals("兔子🐇")) {
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("兔子🐇喝伏特加了, 无比清醒, 不想睡觉");
                }
            }

//            模拟乌龟速度
            if (Thread.currentThread().getName().equals("乌龟🐢")) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }


//            判断比赛是否接结束
            boolean flag = gameOver(i);
//            比赛结束停止程序
            if (flag) {
                break;
            }

            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }
    }

//    判断是否完成比赛
    private boolean gameOver(int steps) {
//        判断是否有胜利者
        if (winner!=null) { //已经存在胜利者了
            return true;
        }{
            if (steps>=100){
                winner = Thread.currentThread().getName();
                System.out.println("最终胜利者 is "+winner);
                return true;
            }
        }
        return false;
    }

//赛道
    public static void main(String[] args) {
        TestRace race = new TestRace();
        new Thread(race,"兔子🐇").start();
        new Thread(race,"乌龟🐢").start();
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DEV--C++小游戏(吃星星(0.5))

目录 吃星星&#xff08;0.5&#xff09; 该版本简介 DEV--C小游戏(吃星星(0.1)) DEV--C小游戏(吃星星(0.2)) 分部代码 头文件 命名空间变量&#xff08;增&#xff09; 副函数&#xff08;新&#xff0c;增&#xff09; 清屏函数 打印地图函数&#xff08;增&…

小红薯视频作品一键克隆,解放双手自动搬运【永久脚本+使用教程】

软件介绍&#xff1a; 小红薯作品搬运神器&#xff0c;软件只需要复制对方的作品链接即可一键克隆搬运到自己的小红书上&#xff0c;再也不用手动去复制粘贴了&#xff0c;批量起号搬运必备神器 设备需求&#xff1a; 电脑 链接&#xff1a;https://pan.baidu.com/s/11MzBqER…

15集合的应用

集合的概念 集合是一个容器&#xff0c;可以容纳其他类型的数据&#xff0c;前面所讲的数组就是一个集合。 所有的集合相关的类和接口都在java.util包下 特点 集合不能直接存储基本数据类型(但是代码上不需要体现&#xff0c;因为Java中有自动装箱)另外集合不能直接存储Java…

数据结构-栈的讲解

栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底&#xff08;因为先进后出&#xff09;。栈中的数据元素遵守后进先出LIFO&#xff08;Last In Firs…

Python GraphQL服务器实现库之tartiflette使用详解

概要 Tartiflette是一个为Python编写的GraphQL服务器实现,它建立在现代异步编程库如asyncio之上,提供了高性能的GraphQL执行环境。Tartiflette专注于提供最佳的开发者体验,支持最新的GraphQL特性。 安装 安装Tartiflette相对简单,但需要依赖于一些系统级的库。 首先,需…

【话题】软件开发的航海图:程序员的实用神器探秘

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景一、代码编写二、版本控制三、测试与调试四、部署与运维五、总结文章推荐 背景 在软件开发的广阔海洋中&#xff0c;每一位程序员都是一位勇敢的航海家&#xff0c…

基于STM32F401RET6智能锁项目(AT24C0X存储芯片)

一、IIC基本介绍 1、IIC通信接口 • I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线 • 两根通信线&#xff1a;SCL&#xff08;串行时钟线&#xff09;、SDA&#xff08;串行数据线&#xff09; • 同步&#xff0c;半双工 • 带数据应答 •…

Java后端的接口参数两个interger 类型情况解决

get请求 &#xff0c;对应请求头 RequestParm, post请求&#xff0c; 对应请求体 &#xff0c;RequestBody 两个Integer参数情况 GetMapping("/insertStaffClass")public R<Void> insertStaffClass(RequestParam Integer staffId,RequestParam List<Integ…

C++ | Leetcode C++题解之第75题颜色分类

题目&#xff1a; 题解&#xff1a; class Solution { public:void sortColors(vector<int>& nums) {int n nums.size();int p0 0, p2 n - 1;for (int i 0; i < p2; i) {while (i < p2 && nums[i] 2) {swap(nums[i], nums[p2]);--p2;}if (nums[i…

python跟C++选哪个?

选择使用Python还是C取决于你的具体需求和项目背景。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 在通信工程行业…

centos7安装zabbix-server

zabbixan-server安装 环境安装zabbix安装zabbix配置apachezabbix-UI前端配置修改zabbix为中文语言 环境 准备&#xff1a; centos7系统、mysql数据库/MariaDB数据库 mysql数据库可参照&#xff1a;https://blog.csdn.net/weixin_61367575/article/details/138774428?spm1001.…

Java(三)---逻辑控制

文章目录 前言1.逻辑控制语句的分类1.顺序结构2.分支结构2.1.if结构2.1.1.if...else语句2.2.2.if ... else if... else语句 2.2.switch语句 3.循环结构3.1.while3.2.break3.3.continue3.4.for循环3.5.do while循环 4.输入输出4.1.输入到控制台4.2.从键盘输入 前言 前两篇文章&…

EfficientNet网络结构详细解读+SE注意力机制+pytorch框架复现

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ 网络详细结构1.1 &#x1f393; MBConv结构1.2 ✨SE注意力机制模块1.3 ⭐️Depthwise Separable Convolution深度可分离卷积1.3.1 普通卷积操作(Convolution)1.3.2 逐深度卷积&#xff08;Depthwise Convoluti…

安全测试|常见SQL注入攻击方式、影响及预防

SQL注入 什么是SQL注入&#xff1f; SQL注入是比较常见的网络攻击方式之一&#xff0c;主要攻击对象是数据库&#xff0c;针对程序员编写时的疏忽&#xff0c;通过SQL语句&#xff0c;实现无账号登录&#xff0c;篡改数据库。 SQL注入简单来说就是通过在表单中填写包含SQL关键…

论文笔记:仅一个进程故障就无法达成共识

仅一个进程故障就无法达成共识 仅一个进程故障指的是在异步的分布式系统中 摘要 异步系统的共识问题&#xff08;consensus&#xff09;涉及一组进程&#xff0c;其中有的进程可能不可靠&#xff08;unreliable&#xff09;。共识问题要求可靠的进程一致地从两个侯选中决定&…

制造业如何挖掘数据价值,附数据分析处理软件推荐

制造业如何挖掘和利用数据价值&#xff1f; 在信息化、智能化高速发展的今天&#xff0c;制造业正迎来一场由数据驱动的深刻变革。数据&#xff0c;作为这场变革的核心驱动力&#xff0c;正被制造业企业深度挖掘和利用&#xff0c;以实现更高效、更智能的生产模式。 制造业在利…

【IP证书】公网IP地址SSL证书怎么获取和安装

一、获取SSL证书 1、选择支持IP证书的CA&#xff1a; 选择一个支持为IP地址颁发SSL证书的证书颁发机构&#xff0c;如JoySSL。 2、准备验证信息&#xff1a; 确保您的公网IP地址是可访问的&#xff0c;并准备好相关的组织信息或IP地址所有权证明&#xff0c;具体取决于CA的…

Goby 漏洞发布|瑞友天翼应用虚拟化系统 /hmrao.php SQL注入漏洞

漏洞名称&#xff1a;瑞友天翼应用虚拟化系统 /hmrao.php SQL注入漏洞 English Name&#xff1a; Ruiyou-Tianyi-App-Virtualization-Delivery-Platform /hmrao.php SQL Injection Vulnerability CVSS core: 9.8 影响资产数&#xff1a;75202 漏洞描述&#xff1a; 瑞友天…

揭秘 HTTP 代理:增强在线活动的安全性和匿名性

HTTP 代理在保护您的在线隐私、增强安全性以及允许访问受限内容方面发挥着关键作用。了解 HTTP 代理的工作原理以及如何有效地利用它们可以让您掌控自己的在线状态和浏览体验。让我们深入研究 HTTP 代理的世界&#xff0c;探索它们的优势、应用程序以及最大化其效用的最佳实践。…

基于SSM SpringBoot vue学校办公自动化系统

基于SSM SpringBoot vue学校办公自动化系统 系统功能 登录注册 个人中心 用户信息管理 部门信息管理 公共通知管理 个人邮箱管理 日常安排管理 管理员管理 签到记录管理 会议管理 开发环境和技术 开发语言&#xff1a;Java 使用框架: SSM(Spring SpringMVC Mybaits)或Spr…