多线程概述及创建

什么是线程?

线程(thread)是一个程序内部的一条执行路径。

我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径。

程序中如果只有一条执行路径,那么这个程序就是单线程的程序。

多线程是什么?

多线程是指从软硬件上实现多条执行流程的技术。

多线程的创建

Thread类

方式一:继承Thread类

1、定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法。

2、创建MyThread类的对象。

3、调用线程对象的start()方法启动线程(启动后还是执行run方法的)。

/**目标:多线程的创建方式一:继承Thread类实现。*/
public class ThreadDemo1 {public static void main(String[] args) {// 3、new一个新线程对象Thread t = new MyThread();// 4、调用start方法启动线程(执行的还是run方法)t.start();for (int i = 0; i < 5; i++) {System.out.println("主线程执行输出:" + i);}}
}/**1、定义一个线程类继承Thread类*/
class MyThread extends Thread{public MyThread(){super();}/**2、重写run方法,里面是定义线程以后要干啥*/@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println("子线程执行输出:" + i);}}
}

 

方式二:实现Runnable接口

1、定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法。

2、创建MyRunnable任务对象。

3、把MyRunnable任务对象交给Thread处理。

4、调用线程对象的start()方法启动线程。

**目标:学会线程的创建方式二,理解它的优缺点。*/
public class ThreadDemo2 {public static void main(String[] args) {// 3、创建一个任务对象Runnable target = new MyRunnable();// 4、把任务对象交给Thread处理Thread t = new Thread(target);// Thread t = new Thread(target, "1号");// 5、启动线程t.start();for (int i = 0; i < 10; i++) {System.out.println("主线程执行输出:" + i);}}
}/**1、定义一个线程任务类 实现Runnable接口*/
class MyRunnable  implements Runnable {/**2、重写run方法,定义线程的执行任务的*/@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("子线程执行输出:" + i);}}
}

 也可以用匿名内部类形式

/**目标:学会线程的创建方式二(匿名内部类方式实现,语法形式)*/
public class ThreadDemo2Other {public static void main(String[] args) {Runnable target = new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("子线程1执行输出:" + i);}}};Thread t = new Thread(target);t.start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("子线程2执行输出:" + i);}}}).start();new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("子线程3执行输出:" + i);}}).start();for (int i = 0; i < 10; i++) {System.out.println("主线程执行输出:" + i);}}
}

 

方式三:利用Callable、FutureTask接口实现(JDK 5.0新增)

1、得到任务对象

         定义类实现Callable接口,重写call方法,封装要做的事情。

         用FutureTask把Callable对象封装成线程任务对象。

2、把线程任务对象交给Thread处理。

3、调用Thread的start方法启动线程,执行任务 。

4、线程执行完毕后,通过FutureTask的get方法去获取任务执行的结果。

FutureTask的API

 示例

/**目标:学会线程的创建方式三:实现Callable接口,结合FutureTask完成。*/
public class ThreadDemo3 {public static void main(String[] args) {// 3、创建Callable任务对象Callable<String> call = new MyCallable(100);// 4、把Callable任务对象 交给 FutureTask 对象//  FutureTask对象的作用1: 是Runnable的对象(实现了Runnable接口),可以交给Thread了//  FutureTask对象的作用2: 可以在线程执行完毕之后通过调用其get方法得到线程执行完成的结果FutureTask<String> f1 = new FutureTask<>(call);// 5、交给线程处理Thread t1 = new Thread(f1);// 6、启动线程t1.start();Callable<String> call2 = new MyCallable(200);FutureTask<String> f2 = new FutureTask<>(call2);Thread t2 = new Thread(f2);t2.start();try {// 如果f1任务没有执行完毕,这里的代码会等待,直到线程1跑完才提取结果。String rs1 = f1.get();System.out.println("第一个结果:" + rs1);} catch (Exception e) {e.printStackTrace();}try {// 如果f2任务没有执行完毕,这里的代码会等待,直到线程2跑完才提取结果。String rs2 = f2.get();System.out.println("第二个结果:" + rs2);} catch (Exception e) {e.printStackTrace();}}
}/**1、定义一个任务类 实现Callable接口  应该申明线程任务执行完毕后的结果的数据类型*/
class MyCallable implements Callable<String>{private int n;public MyCallable(int n) {this.n = n;}/**2、重写call方法(任务方法)*/@Overridepublic String call() throws Exception {int sum = 0;for (int i = 1; i <= n ; i++) {sum += i;}return "子线程执行的结果是:" + sum;}
}

3种方式对比

注意事项

1、为什么不直接调用run方法,而是调用start启动线程?

直接调用run方法会当成普通方法执行,此时相当于还是单线程执行。 只有调用start方法才是启动一个新的线程执行,(看start源码)start方法会把线程加入线程组,每个线程都有机会交给cpu执行,这时线程的run方法会被自动调用,每个线程都有可能还没执行完就被中断从而让cpu执行其他线程,。

2、为什么把主线程任务放在子线程之后?

如果把主线程任务放在子线程之前,那么主线程一定是先跑完的,相当于是一个单线程的效果了。

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

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

相关文章

软件测试不是所有人都适合的

测试工作是一项极其重要的质量保证活动&#xff0c;因此测试部门既是软件发布质量把控的出口&#xff0c;也是客户意见反馈的入口。但是因为之前的不重视&#xff0c;导致了软件测试行业的发展相对滞后&#xff0c;优秀的软件测试工程师非常难得。 一个优秀的测试工程师要对一些…

原生js做打地鼠游戏

抱歉素材有点难找&#xff0c;这次的学习重点是在JS的实现&#xff0c;梳理一下打地鼠的实现逻辑&#xff0c;主要分为三个主要功能函数。 开始游戏&#xff1a;对分数、并根据游戏难度对游戏的倒计时和延迟进行初始化之后&#xff0c;利用setInterval定时器Math.random随机函…

【MySQL】随手笔记(积跬步至千里)

一、常用函数 &#xff08;1&#xff09;uuid() select uuid(); //生成随机数 select replace(uuid(),-,); //将随机数的-去掉 select upper(replace(uuid(),-,)); ///改成大写应用举例&#xff1a; &#xff08;1&#xff09;非自增主键 非自增主键&#xff0c;insert语…

《深入浅出进阶篇》洛谷P4147 玉蟾宫——悬线法dp

上链接&#xff1a;P4147 玉蟾宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P4147 上题干&#xff1a; 有一个NxM的矩阵&#xff0c;每个格子里写着R或者F。R代表障碍格子&#xff0c;F代表无障碍格子请找出其中的一个子矩阵&#xff0c…

【Cocos新手进阶】通过cocos实现可控制的动态加载更新的日志界面效果

本篇文章主要讲解&#xff0c;通过cocos实现可控制的动态加载更新的日志界面效果。 日期&#xff1a;2023年11月15日 作者&#xff1a;任聪聪 效果演示&#xff1a; 效果说明&#xff1a;在一个界面可以动态输出for循环的结果并更新到界面中进行不断加载的日志页面效果&#x…

Java 算法篇-链表的经典算法:根据值删除节点、删除倒数第 n 个节点

&#x1f525;博客主页&#xff1a; 小扳_-CSDN博客 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 链表的创建 2.0 链表的经典算法 - 根据值来删除节点 2.1 根据值来删除节点 - 遍历链表来实现 2.2 根据值来删除节点 - 递归实现 3.0 链表的经典算法 - 删除倒数第 n…

前端element的el-tooltip鼠标经过显示文字,没有文字显示空黑框问题

场景&#xff1a; 有时候在使用element的el-tooltip时会使用三元表达式&#xff0c;满足某个条件后才显示提示文字&#xff0c;否则不展示文字&#xff0c;但是却出现在在没有文字时展示了黑框&#xff0c;如下图&#xff1a; 解决方案&#xff1a; 加一个disabled便可&#…

Spring Cloud Netflix微服务组件-Eureka

CAP理论 分区容忍是能容忍一个或一部分节点挂掉后&#xff0c;整体系统也能正常工作&#xff08;就是别的节点还是活着的&#xff09;&#xff0c;所以分布式系统中P是必须要有的。比如数据库主从架构&#xff0c;主从两个节点之间需要数据同步&#xff0c;主挂了&#xff0c;…

最新PS 2024 虎标正式版来啦,附带AI神经滤镜(支持win/mac)

软件简介 文件名称 PS2024 虎标正式版 支持系统 windows、Mac 获取方式 文章底部 分享形式 百度网盘 小伙伴们&#xff0c;下午好&#xff01;今天给大家的是PS 2024 25.0虎标正式版。 PS 2024 25.0 正式版介绍 经历了多次Photoshop 2023 Beta 测试之后&#xff0c;今天…

Qt高级--(2)自定义标题栏

自定义标题栏 功能点 1.标题栏中最外层布局器使用水平布局器。 2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器&#xff0c;边距和间隔可根据实际情况设置。 3.编写 QSS 样式&#xff0c;并将样式设置到窗口控件中。 4.实现最小化、最大化和关闭窗口按钮功能。 5.实现鼠…

springboot整合vue2实现简单的新增删除,整合ECharts实现图表渲染

先看效果图&#xff1a; 1.后端接口 // 查询所有商品信息 // CrossOrigin(origins "*")RequestMapping("/list1")ResponseBodypublic List<Goodsinfo> list1(){List<Goodsinfo> list goodsService.list();return list;}// 删除 // …

你绝对需要的Facebook养号攻略,教你如何养成耐用号

Facebook 可谓是大家的“老熟人”了&#xff0c;作为全球热门的社交媒体平台&#xff0c;Facebook 一直以来都是社媒营销、跨境电商的重要阵地&#xff0c;但是很多小伙伴们在注册新账号后往往忽略了一个重要的步骤&#xff0c;也是必不可少的一步&#xff0c;那就是养号&#…