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

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方法@Overridepublic 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方法@Overridepublic 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方法@Overridepublic 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;}//    下载图片线程的执行体@Overridepublic 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方法@Overridepublic 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;}//    下载图片线程的执行体@Overridepublic 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;@Overridepublic 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.hqwc.cn/news/707567.html

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

相关文章

centOS忘记密码的处理办法

1、开机后在出现内核选项时&#xff0c;按 e&#xff1b; 2、在Linux 开头的这行&#xff0c;输入 rd.break 如下图&#xff1b; 3、然后&#xff0c;执行&#xff1a;CtrlX&#xff1b; 4、进入之后是 switch_root:/#输入 mount -o rw,remount /sysroot 以读写方式重新挂载 /s…

镊子蜡烛如何设置止盈止损?Anzo Capital昂首资本盈利收场

通过上一篇文章各位聪明的投资者&#xff0c;都已经知道了什么是镊子蜡烛图以及如何抓住反转进行交易&#xff0c;同时也有很多投资者不知道如何设置止盈止损&#xff1f;今天Anzo Capital昂首资本就和各位投资者一起探讨如何盈利收场。 看跌的镊子模式如何交易&#xff1f;首…

FFmpeg多张图片合成视频?

前言 商家在发布商品的时候&#xff0c;大部分情况下是没有视频的&#xff0c;这样往往会造成商品展示不全等问题&#xff0c;而视频制作又比较麻烦&#xff0c;为了解决此痛点&#xff0c;我们需要提供一键合成视频的功能。 之所以选择 FFmpeg&#xff0c;是因为我们期望后续…

推荐网站(11)Autodraw免费画画自动识别网站

今天我想分享一个神奇的网站&#xff0c;它可以根据你所画的内容自动生成相应的风格&#xff0c;对于那些不太擅长画画的朋友来说简直是个福音&#xff0c;再也不用担心自己不擅长绘画了&#xff01; 草率的画一只鸟 比如我们选择第一个看看&#xff0c;比我画的好多了 链接直…

前端工程化 - 快速通关 - vue

目录 npm 2.1环境 2.2命令 2.3使用流程 Vite 3.1简介 3.2实战 Vue3 4.1组件化 4.2SFC 4.3Vue工程 4.4基础使用 4.5进阶用法 4.6总结 npm npm 是 nodejs 中进行 包管理 的工具&#xff1b; 下载&#xff1a;Node.js — Run JavaScript Everywhere 2.1环境 ●安…

Springboot整合 Spring Cloud Alibaba Sentinel

1.Sentinel介绍 官方文档地址&#xff1a; https://sentinelguard.io/zh-cn/docs/introduction.html https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入…

什么样的技术管理者会被委以重任?

很多技术管理者在职场遭遇瓶颈&#xff0c;长期在中基层管理岗位上徘徊&#xff0c;似乎怎么努力都没有用&#xff0c;难以突破。 而那些被委以重任的技术管理者&#xff0c;往往展现出一些共同的特征&#xff0c;这些特征有助于他们在职业生涯中脱颖而出&#xff0c;今天就聊…

CVE-2022-1015:nf_tables 中整数溢出导致的栈溢出

文章目录 前言漏洞分析漏洞利用OOB ReadOOB Write exploit修复 前言 影响版本&#xff1a;v5.12.0~v5.17.0 测试版本&#xff1a;v5.17.0 编译选项&#xff1a; CONFIG_NF_TABLESy CONFIG_NETFILTER_NETLINKy CONFIG_BINFMT_MISCy CONFIG_USER_NSy CONFIG_E1000y CONFIG_E1…

手机恢复数据:方法与注意事项

手机数据恢复是许多用户在面对意外数据丢失时迫切需要解决的问题。无论是误删文件、系统故障还是其他原因导致的数据丢失&#xff0c;采取正确的恢复方法至关重要。在本文中&#xff0c;我们将探讨手机恢复数据的方法与注意事项&#xff0c;帮助您有效地找回丢失的重要信息。 手…

【K8s】专题四:Kubernetes 安装方法之 Sealos

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、Sealos 简介 二、Sealos 下载、安装 三、Sealos 部署 Kubernetes 集群 四、Sealos 常…

Cocktail for Mac 激活版:一站式系统优化与管理神器

Cocktail for Mac是一款专为Mac用户打造的系统优化与管理工具&#xff0c;凭借其强大的功能和简便的操作&#xff0c;赢得了广大用户的喜爱。这款软件集系统清理、修复和优化于一身&#xff0c;能够帮助用户轻松解决Mac系统中的各种问题&#xff0c;提高系统性能。 Cocktail fo…

【Open AI】GPT-4o深夜发布:视觉、听觉跨越式升级

北京时间5月14日1点整&#xff0c;OpenAI 召开了首场春季发布会&#xff0c;CTO Mira Murati 在台上和团队用短短不到30分钟的时间&#xff0c;揭开了最新旗舰模型 GPT-4o 的神秘面纱&#xff0c;以及基于 GPT-4o 的 ChatGPT&#xff0c;均为免费使用。 本文内容来自OpenAI网站…