【Java基础】线程的概念、特点及创建线程的三种方式

线程概念

程序: 是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
进程: 是执行程序的一次执行过程,她是一个动态的概念,是系统资源分配的单位。正在运行的程序在内存中开辟相应的空间。
线程: 负责程序执行的一条执行路径,是CPU调度和执行的单位。

进程和线程的关系: 程的执行实际上是线程在执行,一个进程可以包含若干个线程,进程中至少有一个线程,不然没有存在的意义。

注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下, 在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。

普通方法调用和多线程
普通方法调用和多线程的对比
线程概念:
◆ 线程就是独立的执行路径;
◆ 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
◆ main()称之为主线程,为系统的入口,用于执行整个程序;
◆ 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的;
◆ 线程不一定立即执行,cpu安排调度;
◆ 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
◆ 线程会带来额外的开销,如cpu调度时间,并发控制开销;
◆ 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

多线程特点

  • 多线程实现了同时执行的效果(不同功能或相同功能的同时执行)。
    多线程不一定能提高效率,但能充分利用CPU,关键是实现了在一个程序中,不同功能或相同功能的同时执行的效果

  • java程序是否是多线程程序:
    有一个负责执行main中代码的线程,就是主线程
    有一个负责垃圾回收的线程,垃圾回收线程

    垃圾回收线程:
    Object的finalize()方法,等垃圾收集器确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象

    强制执行垃圾回收线程:
    System.gc()运行垃圾回收线程,是一个守护线程,优先级低,主线程的其他代码优先运行,主线程结束时,即使它没有回收完,也要结束。

    在这里插入图片描述

    多线程的运行结果是不确定的

  • 线程执行的功能不同,则对应的功能代码所写的位置也不同
    1.主线程执行的功能代码写在main方法中
    2.垃圾回收线程执行的功能代码写在finalize方法中

    把线程执行的功能称为线程的任务
    线程的任务不同,则任务代码所写的位置不同

互不影响

每个线程在栈中都有自己的一块内存,各自执行自己的任务,当所有线程全部执行完,整个程序才结束。
一个线程发生异常只是线程自己的问题,不会影响其它线程。
在这里插入图片描述
在这里插入图片描述

创建线程的方式

一、继承 Thread 类

  1. 自定义线程类继承Thread类,因为Thread是线程类,则这个子类也是线程类了;
  2. 在子类中重写run方法 void run(),该子类创建的对象就是一个子线程,线程执行的任务代码需要书写在run方法中;
    (注:run方法是重写的方法,不能使用throws抛出异常,原方法没有)
  3. 创建线程对象;
  4. 调用**start()**方法启动线程。
class Person extends Thread{…………public void run(){//任务for(int i=1;i<=10;i++){sop(Thread.currentThread().getName()+"…………"+i);//线程默认的名字:Thread-编号(编号从0开始)}}
}
class Demo5{public static void main(String[] args){ //主线程Person ren1=new Person("张三");//创建了一个线程Person ren2=new Person("李四");//创建了一个线程//ren1.run(); //普通的方法调用,并没有启动线程//启动线程,当线程抢到cpu时会执行run方法中的任务代码ren1.start();ren2.start();sop(Thread.currentThread().getName());//主线程名字:main}
}

不建议使用:避免OOP单继承局限性

卖票问题——四个窗口卖票:
创建四个线程,四个线程的任务都是卖票,只需要定义一个Thread的子类。
出现了一张票被卖了4次的问题,原因是每个Ticket对象中都有一个num成员。需要让四个线程共享50张票:把票修饰为static的,则票就只有一份了。
不是所有情况都能被修饰为static的,使用创建线程的第二种方式来解决。

创建线程的第一种方式:

  • Ticket类既是任务类也是线程类
    四个线程需要创建四个Ticket对象,每个对象中都有一份儿资源,所以四个线程就有了四份儿资源

创建线程的第二种方式:

  • Ticket类只是任务类,只需创建Ticket的一个对象,只有一份儿资源
    让四个线程都执行相同的任务

二、实现 Runnable 接口

  1. 创建一个实现了Runnable接口的类(该类只需重写run方法,所以该类是专门用来定义线程执行的任务代码的)
  2. 创建实现了Runnable接口的类的对象
  3. 创建线程对象——使用Thread类 Thread(Runnable target)
class Ticket implements Runnable {//任务类private int num=50;public void run(){while(true)if(num>0)sop(Thread.currentThread().getName()+"…sale…"+(num--));} 
}
class Test implements Runnable{  public void run(){……}  }
class Demo8 {public static void main(String[] args) {Ticket t=new Ticket(); //任务对象Test tt = new Test();
//Thread是线程类,线程和任务分别面向对象,那么线程执行的任务不再是固定的了Thread t1=new Thread(tt); Thread t2=new Thread(t);Thread t3=new Thread(t);Thread t4=new Thread(t);t1.start();t2.start();t3.start();t4.start();//new Thread(t).start();}
}
Thread类实现了Rannable接口
  • Thread(Runnable target)
class Test1 implements Runnable{public void run(){System.out.println("Hello World!");}
}
class Test2 extends Thread{public void run(){System.out.println("Hello");}
}
class Demo9{public static void main(String[] args) {//Test1 t1=new Test1();//Thread tt = new Thread(t1);//Test2 t2 = new Test2();Thread t=new Thread(()->System.out.println("Hello"));t.start();   }
}

推荐使用:避免单继承局限性,灵活方便,方便一个对象被多个线程使用

//一份资源
StartThread station = new StartThread();
//多个代理
new Thread(station,"小明").start();
new Thread(station,"小红").start();
new Thread(station,"老师").start();
对比

继承了Thread的类,既是线程类,同时也是任务类,用该类创建的线程执行的任务是固定的;
实现了Rannable接口的类是任务类,线程和任务分别面向对象,那么线程执行的任务不再是固定的了。

三、实现Callable接口(了解即可)

  1. 实现Callable接口,需要返回值类型

  2. 重写call方法,需要抛出异常

  3. 创建目标对象

  4. 创建执行服务:

    ExecutorService service= Executors.newFixedThreadPool(3);

  5. 提交执行:Future<Boolean> r1= service.submit(t1);

  6. 获取结果:boolean rs3=r3.get();

  7. 关闭服务:service.shutdownNow();

Callable的好处
  1. 可以定义返回值
  2. 可以抛出异常

利用Callable接口改造下载图片案例

package com.shan.demo4;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
public class TestCallable implements Callable<Boolean> {
public String url;
public String name;
public TestCallable(String url,String name){
this.url=url;
this.name=name;
}
@Override
public Boolean call() {
//run方法线程体
WebDownloader webDownloader = new WebDownloader();
webDownloader.Downloader(url,name);
System.out.println("下载的文件名为:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable t1 = new TestCallable("https://img-home.csdnimg.cn/images/20201124032511.png","3-1.png");
TestCallable t2 = new TestCallable("https://img-home.csdnimg.cn/images/20210910112431.gif","3-2.gif");
TestCallable t3 = new TestCallable("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png","3-3.png");
//创建执行服务:
ExecutorService service= Executors.newFixedThreadPool(3);
//提交执行:
Future<Boolean> r1= service.submit(t1);
Future<Boolean> r2= service.submit(t2);
Future<Boolean> r3= service.submit(t3);
//获取结果:
boolean rs1=r1.get();
boolean rs2=r2.get();
boolean rs3=r3.get();
//关闭服务:
service.shutdownNow();
}
}
class WebDownloader{
public void Downloader(String url,String name){
try {FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {e.printStackTrace();System.out.println("IO异常,Downloader方法出现问题");
}
}
}

方法二:利用FutureTask

//方法二:
FutureTask<Boolean> futureTask=new FutureTask<>(new TestCallable("https://img-home.csdnimg.cn/images/20201124032511.png","1.png"));
new Thread(futureTask).start();
Boolean aBoolean = futureTask.get();
System.out.println(aBoolean);

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

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

相关文章

2024-万相台 无界 运营实战4.0最新版,店铺 运营推广必修 理论+实操

课程内容 基 础 操 作 直通车选择投放关键词 直通车怎么选择投放人群 直通车抢位助手怎么用 直通车创意如何设置投放 直通车报表的解读分析 直通车低价引流 智能计划投放技巧 均匀测款计划技巧 周期性投放计划技巧 词包计划投放方案 中心词计划投放方案 转 化 率 …

2024拼多多 最新理论+实战干货,从入门到精通全链路多角度学习-7节课

基于最新规则理论结合实际的干货 课程内容&#xff1a; 01 2024年多多防比价新规则破局理论课与实操课.mp4 02 24年多多强付费第二节课基础内功.mp4 03 24年多多强付费第三节课直通车实操 .mp4 04 24年多多强付费第一节课市场定价格段,mp4 05 24年多多自然流第一节课市场…

限流开关:HC5504,70mΩ,5V USB 高侧可调门限限流负载开关,供应USB总线/自供电集线器USB周边、笔记本电脑,平板电脑、电池充电器

限流开关&#xff1a; HC5504&#xff1a;70mΩ&#xff0c;5V USB 高侧可调门限限流负载开关 概述&#xff1a;HC5504是一款适用于5V应用的可调限流门限的USB接口输出保护芯片。芯片内部集成了过流保护、短路保护、过温保护、欠压保护等功能&#xff0c;在输出发生过流、短路…

【Java】如何让系统抗住双十一的预约抢购活动?

一、问题解析 在大促活动期间&#xff0c;“预约抢购”已经是各大电商平台的主要促销手段&#xff0c;京东自然也会和一些大的供应商合作&#xff0c;推出一些低价的爆款产品&#xff0c;比如 2019 年的 “1499 元抢购飞天茅台”活动&#xff0c;就让很多人每天准时准点拿着手…

720云「3D空间漫游」功能爆发!户型标注、自动导览、切换视图…

一、新增 [开场封面] 支持图片、视频开场 作品第一印象必须惊艳&#xff01;使用频率极高的功能&#xff0c;终于给3D漫游安排上啦~你可以自定义上传一张图片或一段视频&#xff0c;支持对桌面端、移动端分别进行设置并预览&#xff0c;完美适配不同终端。 二、升级模型交互体验…

《QT从基础到进阶·四十二》QT运行后项目图标,exe图标问题,VS加载.pro文件问题

1、QT图标有时候不能正常显示&#xff0c;不管是加到qrc还是用绝对路径&#xff0c;都无法正常显示&#xff0c;之前是可以的&#xff0c;具体原因目前还不太清楚&#xff0c;我在VS项目——vcpkg——use vcpkg把否改为是就可以了 2、出现无法定位程序输入点的报错&#xff0c…

【教学类-13-05】20240604《数字色块图-5*7*8-A4横板-横切》中4班

背景需求&#xff1a; 【教学类-13-04】20230404《数字色块图判断密码是否正确-5*7*8-A4横板-横切》&#xff08;中班主题《我爱我家》)_图案密码色块-CSDN博客文章浏览阅读530次。【教学类-13-04】20230404《数字色块图判断密码是否正确-5*7*8-A4横板-横切》&#xff08;中班主…

常用运维工具之 WGCLOUD(国产软件)介绍

WGCLOUD是一款免费开源的运维监控软件&#xff0c;轻量高效&#xff0c;部署方便&#xff0c;上手简单&#xff0c;界面简单流畅 WGCLOUD是国产运维软件&#xff0c;可以适配大部分的信创环境&#xff0c;比如麒麟、统信等操作系统 WGCLOUD具体支持监控的操作系统如下&#x…

s32k314【入门新手篇】-开发环境安装【ds32开发平台】

软件包下载 登录nxp官网下载&#xff1a;https://www.nxp.com/ 然后输入关键字&#xff1a;S32 查看 下载安装包 以上三步请先注册好并登录你的个人账号 下载完之后如下&#xff1a; 软件安装 eb安装并激活【试用版】 激活 2 安装ds 弹出什么就安装什么就好了。 …

kettle从入门到精通 第六十五课 ETL之kettle 执行动态SQL语句,轻松实现全量增量数据同步

本次课程的逻辑是同步t1表数据到t2表&#xff0c;t1和t2表的表机构相同&#xff0c;都有id&#xff0c;name,createtime三个字段。 CREATE TABLE t1 (id bigint NOT NULL AUTO_INCREMENT,name varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,cr…

C++系列-STL简介

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 什么是STL STL是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 STL的版本 原始版本 Alexander Stepa…

History 模式和 Hash 模式路由的区别、优缺点及在开发生产环境中的注意事项

在现代单页应用&#xff08;SPA&#xff09;开发中&#xff0c;前端路由是至关重要的一部分。常见的路由模式有两种&#xff1a;History 模式和 Hash 模式。本文将详细探讨这两种模式的区别、优缺点&#xff0c;并在开发和生产环境中的注意事项。 路由模式简介 Hash 模式 H…

网工内推 | 上市公司网工,Base广东,思科DE/IE认证优先

01 广州赛意信息科技股份有限公司 &#x1f537;招聘岗位&#xff1a;技术架构师 &#x1f537;职责描述&#xff1a; 1、设计、开发和维护工业数据库及其架构&#xff0c;包括数据采集、存储、处理和分析的工具和系统。 2、开发和维护数据管道和工作流程&#xff0c;确保数据…

通过Excel,生成sql,将A表数据插入B表

文章目录 投机取巧的方式,进行表数据初始化通过navicat搜索A表数据,然后复制进excel中通过excel的函数方式,将该批量数据自动生成插入B表的sql语句然后一次性拷贝生成的sql语句,放进navicat中一次执行,直接完成数据初始化

美容美发门店收银管理系统源码分享-美业系统App端闪退怎么办?

美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 活动促销 PC管理后台、手机APP、iPad APP、微信小程序 ▶ 手机App应用闪退怎么办&#xff1f;博弈美业系统为例 • 可能原因&#xff1a; 1、手机版本过低 2、未更新…

域内路由选择协议——RIP

例题 RIP&#xff08;Routing Information Protocol&#xff09;是一种基于距离向量的路由协议&#xff0c;使用跳数作为度量标准来决定最优路径。下面我们详细分析为什么RIP协议要这样设计。 RIP协议的基本工作原理 距离向量算法&#xff1a; 每个路由器维护一张路由表&…

MySQL Hints:控制查询优化器的选择

码到三十五 &#xff1a; 个人主页 MySQL Hints是优化数据库查询性能的一种强大工具。它们允许开发者在SQL查询中嵌入指令&#xff0c;以影响MySQL优化器的决策过程。在某些情况下&#xff0c;优化器可能无法选择最佳的查询执行计划&#xff0c;这时我们可以使用Hints来引导优化…

【光谱特征选择】连续投影算法SPA(含python代码)

目录 一、背景 二、代码实现 三、项目代码 一、背景 连续投影算法&#xff08;Successive Projection Algorithm&#xff0c;SPA&#xff09;是一种用于光谱分离的简单且有效的算法。它主要应用于高光谱图像处理&#xff0c;用于提取混合光谱数据中的端元&#xff08;endme…

生命周期钩子小案例

文章目录 一、在created中发送数据二、在mounted中获取焦点 一、在created中发送数据 <body><div id"app"><ul><li v-for"(item, index) in list" :key"item.id" class"news"><div class"left"…

词法分析器的设计与实现--编译原理操作步骤,1、你的算法工作流程图; 2、你的函数流程图;3,具体代码

实验原理&#xff1a; 词法分析是编译程序进行编译时第一个要进行的任务&#xff0c;主要是对源程序进行编译预处理之后&#xff0c;对整个源程序进行分解&#xff0c;分解成一个个单词&#xff0c;这些单词有且只有五类&#xff0c;分别时标识符、关键字&#xff08;保留字&a…