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

news2024/11/29 4:43:54

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();
    }

}

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

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

相关文章

有手就会做!保姆级Jmeter分布式压测操作流程(图文并茂)

分布式压测原理 分布式压测操作 保证本机和执行机的JDK和Jmeter版本一致配置Jmeter环境变量配置Jmeter配置文件 上传每个执行机服务jmeter chmod -R 755 apache-jmeter-5.1.1/ 执行机配置写自己的ip 控制机配置所有执行机ip,把server.rmi.ssl.disable改成true 将本机也作为压…

ansible -playbook运维工具、语法、数据结构、命令用法、触发器、角色

目录 配置文件 基本语法规则&#xff1a; YAML支持的数据结构 playbook核心元素 ansible-playbook用法&#xff1a; 触发器 特点&#xff1a; 角色&#xff1a; 习题&#xff1a; 配置文件 playbook配置文件使用yaml语法&#xff0c;YAML 是一门标记性语言,专门用来写配…

QT函数整理

目录 1. 适应高分辨率函数 1. 适应高分辨率函数 自动适应调整设备安装QT的UI分辨率&#xff1a; QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 加载位置&#xff1a;

主机扫漏:Apache Tomcat 环境问题漏洞(CVE-2023-46589)

文章目录 引言I 修复此安全问题see also引言 Apache Tomcat存在环境问题漏洞,该漏洞源于存在不正确的输入验证漏洞,可能会导致将单个请求视为多个请求,从而在反向代理后面出现请求走私。 Tomcat did not correctly parse HTTP trailer headers. A specially crafted traile…

2024版有审图号的SHP行政区划

我们之前分享过一些行政区划数据&#xff0c;但都没有审图号。 今天为大家分享一个2024版且有审图号的行政区划&#xff0c;文件格式为SHP且坐标无偏移。 如果你需要该数据&#xff0c;请在文末查看获取方法。 全国省级行政区划 全国共23个省&#xff0c;5个自治区&#xf…

【消息队列】消息中间件介绍

目录 电商系统引发的思考实现支付业务时使用串行操作&#xff08;同步&#xff09;串行操作存在的问题根据上述的几个问题&#xff0c;在设计系统时可以明确要达到的目标 消息中间件【MQ&#xff08;Message Queue&#xff09;】使用场景1.应用解耦2.异步提速3.流量削峰举个栗子…

ROS控制器插件及机器人模型

ROS中的控制器插件 ros_control 1、ROS为开发者提供的机器人控制中间件 2、包含一系列控制器接口、传动装置接口、硬件接口、控制器工具箱等 3、可以帮助机器人应用功能包更快速落地&#xff0c;提高开发效率 一、控制器管理 提供一种通用的接口来管理怒同的控制器 二、控…

GIAT: 蛋白质结构预测的新利器

瑞典Karolinska研究院在瑞典政府赞助下由Ben Murrell等研究团队在AlphaFold 3最新报告后提出这篇论文提出了一种非常有趣和创新的方法来生成蛋白质骨架结构,称为生成式不变角度转换器(GIAT)。与现有的主要基于扩散模型和流匹配的方法不同,GIAT采用了类似于大型语言模型(如GPT)中…

DDOS攻击实战演示,一次DDOS的成本有多低?

DDoS攻击成本概览 分布式拒绝服务&#xff08;DDoS&#xff09;攻击以其低廉的启动成本和惊人的破坏力著称。攻击者通过黑市轻松获取服务&#xff0c;成本从几十元人民币的小额支出到针对大型目标的数千乃至数万元不等。为了具体理解这一成本结构&#xff0c;我们将通过一个简…

东芝移动硬盘数据恢复方法有哪些

谁能懂我此刻的心情啊&#xff01;移动硬盘用起来真的超级方便&#xff0c;如今我的工作几乎都离不开它&#xff0c;用来存放各种重要文件。可是&#xff0c;让人头疼的事情发生了&#xff0c;昨天我发现移动硬盘里的部分数据竟然莫名其妙地消失了&#xff01;这可咋整啊&#…

乡村振兴与乡村旅游深度融合:依托乡村自然和文化资源,发展乡村旅游产业,促进农民增收致富,打造特色美丽乡村

目录 一、引言 二、乡村振兴与乡村旅游的内在联系 三、依托乡村自然和文化资源发展乡村旅游产业 &#xff08;一&#xff09;挖掘乡村自然资源优势&#xff0c;打造特色旅游品牌 &#xff08;二&#xff09;挖掘乡村文化资源内涵&#xff0c;丰富旅游活动内容 四、促进农…

一年IF涨幅10.527,一跃4区变1区,这本IEEE低调,但实力不容小觑!

本周投稿推荐 SSCI • 2区社科类&#xff0c;3.0-4.0&#xff08;社科均可&#xff09; EI • 计算机工程类&#xff08;接收广&#xff0c;录用极快&#xff09; SCI&EI • 4区生物医学类&#xff0c;1.5-2.0&#xff08;录用率99%&#xff09; • 1区工程类&#…

四川易点慧电商抖音小店稳扎稳打,揭秘其成功背后的秘密武器

在数字经济风起云涌的今天&#xff0c;四川易点慧电子商务有限公司以其独特的商业洞察力和创新经营策略&#xff0c;在抖音小店平台上稳扎稳打&#xff0c;赢得了广大消费者的青睐。那么&#xff0c;这家公司究竟是如何在竞争激烈的电商市场中脱颖而出的呢&#xff1f;让我们一…

目标检测——YOLOv9算法解读

论文&#xff1a;YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information (2024.2.21) 作者&#xff1a;Chien-Yao Wang, I-Hau Yeh, Hong-Yuan Mark Liao 链接&#xff1a;https://arxiv.org/abs/2402.13616 代码&#xff1a;https://github.com/W…

项目总结(5月13号)

从做聊天室项目到现在&#xff0c;陆陆续续完成了部分项目的功能点。 下面是我的项目构思 这里介绍一下项目的关键功能点&#xff0c;私聊和群聊。 因为我用的是非阻塞io&#xff0c;所以聊天窗口不能多开&#xff0c;当只开一个窗口进行聊天时&#xff0c;可以实现聊天信息的…

✬✬✬宁波iso14001认证:环境保护的“绿色光环”加持✬✬✬

&#x1f352;宁波iso14001认证&#xff1a;&#x1f497;环境保护的“绿色光环”加持&#x1f335; &#x1f353;说到环境保护&#xff0c;&#x1f602;我可是满满的热情啊&#xff01;⌚最近&#xff0c;我们公司成功&#x1f688;获得了ISO14001认证&#xff0c;&#x1f…

研究幽灵漏洞及其变种(包括但不限于V1-V5)的攻击原理和基于Github的尝试

一、研究幽灵漏洞及其变种(包括但不限于V1-V5)的攻击原理 1.1 基本漏洞原理(V1) 幽灵漏洞的基本原理是由于glibc库中的gethostbyname()函数在处理域名解析时,调用了__nss_hostname_digits_dots()函数存在缓冲区溢出漏洞。 具体来说,__nss_hostname_digits_dots()使用一个固定…

铁路/党员干部网评该如何去投稿呢?

为了推动网宣工作的正常运行网宣文章还能够有所突破&#xff0c;那么写作出高质量的文章就成为了我们的坚韧利剑了&#xff0c;我们在写作的时候需要用到软文写作技巧的手法来进行写作。俗话说得好冰冻三尺非一日之寒&#xff0c;在网上能够写作出吸引人的文章作者都是有较长的…

前端动态旋转地球背景

效果图 贴下源码 <template><div class"map-bg"><div class"canvas" id"canvs"></div><canvas class"canvasxk" id"canv"></canvas></div> </template><script setup …

「网络流 24 题」星际转移【最大流、残余网络上加边、分层(分时)图】

「网络流 24 题」星际转移 1 ≤ n ≤ 13 , 1 ≤ m ≤ 20 , 1 ≤ k ≤ 50 1 \leq n \leq 13, 1\leq m \leq 20, 1 \leq k \leq 50 1≤n≤13,1≤m≤20,1≤k≤50 思路 我们用 s h i p [ i ] [ j ] ship[i][j] ship[i][j] 表示飞船 i i i 在时刻 T T T mod r i j r_i j ri​…