你好,看完你的博客文章,感觉很不错!希望与你网站首页友情链接 流量卡知识网 http://53go.cn/ 专注于移动/联通/电信推出的大流量多语音活动长短期套餐手机卡的相关知识的介绍普及听说互换友情链接可以增加网站的收录量,特此来换,如果同意的话就给internetyewu@163.com[微信ganenboy]发信息或者就在此回复下吧!【建站问题也可以一起讨论!】
你好,看完你的博客文章,感觉很不错!希望与你网站首页友情链接 流量卡知识网 http://53go.cn/ 专注于移动/联通/电信推出的大流量多语音活动长短期套餐手机卡的相关知识的介绍普及听说互换友情链接可以增加网站的收录量,特此来换,如果同意的话就给internetyewu@163.com[微信ganenboy]发信息或者就在此回复下吧!【建站问题也可以一起讨论!】
你好
http://bigota.d.miui.com/V14.0.9.0.TLJCNXM/ingres_images_V14.0.9.0.TLJCNXM_20230323.0000.00_13.0_cn_chinatelecom_aff802bb3e.tgz
已添加贵站友链 Southerly 个人博客 || http://www.southerly.top || https://www.southerly.top/imgs/favicon.ico || 一个正在努力搬砖的兼职程序员,记录生活,分享生活,欢迎大家来访。
目前这种不行了
老哥呀,现在这种方法还能爬到数据嘛?可以聊聊不
https://www.aliyundrive.com/s/5N2bKDVZfxC
https://wwi.lanzoup.com/iU6FZ0o4as1i
04824ADB9F824ADB9F0400824ADB9F000F
https://lihh.lanzouf.com/ij6c80nhq7rg
https://cloud.189.cn/web/share?code=FvuIbuJBnEVr
https://lihh.lanzouf.com/ij6c80nhq7rg
https://developer.aliyun.com/plan/student?taskCode=vmfeitian2023&recordId=5246709&undefined&share_source=copy_link
已加,三天之后检查没加本站链接 就下了
首页
大佬聚集地
欢迎大家
教程分享
每日一看
Search
1
欢迎来到河马博客
41,756 阅读
2
守护者群管小栗子框架下载教程
40,887 阅读
3
烟花模拟器(php)
35,661 阅读
4
外链搜索引擎优化如何发布
13,619 阅读
5
一键搭建表白墙源码+教程
13,255 阅读
软件分享
教程分享
源码分享
游戏攻略
百科知识
SEO课程
登录
Search
标签搜索
推特
升学考试
账号
数学
饺子
笔记本电脑
笔记本
研究生考试
字符
英语
函数
马斯克
笔记本电脑排名前十
操作
初一
联想
考研
广告
注册
账户
河马
累计撰写
7,418
篇文章
累计收到
81
条评论
今日撰写
50
篇文章
首页
栏目
软件分享
教程分享
源码分享
游戏攻略
百科知识
SEO课程
页面
大佬聚集地
欢迎大家
教程分享
每日一看
用户登录
登录
搜索到
1450
篇与
的结果
2023-12-07
干货满满(java多线程讲解)java多线程简单实例,Java多线程知识点详解,包含实例,搞懂多线程看这一篇文章就够了,java多线程实例,
序欢迎来到全网最完整的Java入门系列教程!!! 本教程将包含基础知识、进阶知识、常用框架等,循序渐进地分享Java中必须掌握的知识和技术。跟着老K的教程每天学习一点,你会发现入门Java没有想象中那么难。之前,我们通过4期的内容分享了IO文件读写和它的实战。本期开始,我们将进入Java进阶知识的最后一个模块知识——多线程。实现多线程的方法有很多,我们会介绍三个最具代表性的实现方法:Thread类、Runnable接口和Callable接口。如果你正在学习Java,不妨收藏这篇文章,或者关注我,定期收获与Java有关的知识和项目信息!Java进阶知识前十一课的内容,可拉到文章末尾获取。正式开始本期内容的分享:一、Thread类Thread类是控制多线程的类。代码示例:import java.util.Random;public class ThreadDemo {public static void main(String[] args) {SubThread threadA = newSubThread();threadA.setName("A线程");SubThread threadB = new SubThread();threadB.setName("B线程");threadA.start();threadB.start();}static class SubThread extends Thread {@Overridepublic void run() {int num = 0;for (int i = 1; i <= 5; i++) {num += new Random().nextInt(10);System.out.println(this.getName() + "在" + i + "时的累加和为" + num);}}}}运行结果:A线程在1时的累加和为0B线程在1时的累加和为9A线程在2时的累加和为6B线程在2时的累加和为9A线程在3时的累加和为8B线程在3时的累加和为9A线程在4时的累加和为15B线程在4时的累加和为11A线程在5时的累加和为19B线程在5时的累加和为11说明:上例中,SubThread是Thread的子类,用于设置自定义的线程逻辑;Thread线程是通过定义子类,重写内部方法run来实现自定义线程的,重写的run方法里就是自定义的执行逻辑;Thread类及其子类,都包含start方法,用来启动当前线程;从上例的运行结果可以看出,A、B两个进程不是“先A后B”的顺序,而是交替执行,这体现了多线程的逻辑;由于多线程的执行存在随机性,加上上例中的线程逻辑中加入了随机数,所以每次执行的结果和顺序都不会一样。二、Runnable接口Runnable是一种通过接口实现线程逻辑的方法,使用上和Thread类似,不同程序员习惯不同,不管Runnable还是Thread,都是实现线程的好方法。示例代码:import java.util.Random;public class ThreadDemo {public static void main(String[] args) {Thread threadA = new Thread(new SubThread());threadA.setName("A线程");Thread threadB = newThread(new SubThread());threadB.setName("B线程");threadA.start();threadB.start();}static class SubThread implements Runnable {@Overridepublic void run() {int num = 0;for (int i = 1; i <= 5; i++) {num += new Random().nextInt(10);System.out.println(Thread.currentThread().getName() + "在" + i + "时的累加和为" + num);}}}}运行结果:A线程在1时的累加和为5B线程在1时的累加和为8A线程在2时的累加和为14B线程在2时的累加和为17A线程在3时的累加和为20B线程在3时的累加和为17A线程在4时的累加和为28B线程在4时的累加和为18A线程在5时的累加和为29B线程在5时的累加和为21说明:Runnable也有run方法,使用上和Thread的run相似;Runnable可以通过作为Thread的构造参数实现线程功能;Runnable接口的实现类没有start方法,要执行线程必须以参数方式传入Thread,利用Thread的start方法启动。三、Callable接口使用Thread或者Runnable的时候,有一个缺陷:就是因为是继承父类方法重写,所以不能规定返回值,而Callable能比较好地解决这个问题。示例代码:importjava.util.Random;import java.util.concurrent.*;public class ThreadDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService exe = Executors.newFixedThreadPool(3);SubThread threadA = new SubThread();threadA.name = "A线程";SubThread threadB = newSubThread();threadB.name ="B线程";Future<Integer> f1 = exe.submit(threadA);Future<Integer> f2 = exe.submit(threadB);exe.shutdown();System.out.println(threadA.name +"的总和为" + f1.get());System.out.println(threadB.name + "的总和为" + f2.get());}static class SubThread implements Callable<Integer> {public String name;@Overridepublic Integer call() {int num = 0;for (int i = 1; i <= 5; i++) {num += new Random().nextInt(10);System.out.println(this.name + "在" + i + "时的累加和为" + num);}return num;}}}运行结果:A线程在1时的累加和为0B线程在1时的累加和为9A线程在2时的累加和为2B线程在2时的累加和为18A线程在3时的累加和为10B线程在3时的累加和为22A线程在4时的累加和为17B线程在4时的累加和为30A线程在5时的累加和为25B线程在5时的累加和为30A线程的总和为25B线程的总和为30说明:Callable接口可以有返回值,此处的泛型用来规范返回值的数据类型,此处为Integer;ExecutorService是用来管理线程池的类,Executors是线程管理的一个核心类;Executors.newFixedThreadPool可以固定线程池中线程数量,返回类型为ExecutorService;Callable接口实现类,需要放在ExecutorService中通过submit方法启动;submit的线程,返回的是一个Future类型的数据,Future里会包含Callable.call的返回值;通过Future的方法get,可以获取Callable.call的返回值,用以后续的程序;ExecutorService由于是充当线程池的角色,所以不会因为线程结束而自动关闭,需要通过shutdown方法进行关闭。以上就是有关于Java多线程的三个最具代表性的实现方法。大家可以收藏这篇文章,多读几遍慢慢消化。如果你对老K分享的内容有任何疑问,欢迎随时在评论区留言或者私信我。本期的内容就分享到这里。正在学习的小伙伴记得给老K一个赞哦,你的支持是我持续输出课程内容最大的动力!Java进阶知识前十一课的内容,可点击下方获取:如何优雅的处理异常--Java进阶知识讲义系列(一)包装器类装箱与拆箱的艺术——Java进阶知识讲义系列(二)一文讲透Java字符串——Java进阶知识讲义系列(三)List的用法和实例详解——Java进阶知识讲义系列(四)Set的用法和实例详解——Java进阶知识讲义系列(五)Map的用法和实例详解——Java进阶知识讲义系列(六)常用集合的排序方法——Java进阶知识讲义系列(七)I/O流之File类的用法和实例详解——Java进阶知识讲义系列(八)「Java进阶」I/O操作必备知识点:字节流读写实例讲解「Java进阶」I/O操作必备知识点:关于字符流读写的实例讲解I/O流实战应用精选:网络图片下载器 Java必备基本功结束语我是专注于开发领域的@老K玩代码 ,会持续生产关于如何学习编程语言的优质内容。如果你想学习Java编程,或者想精进你的Java编程能力,可以关注我。如果你对开发、编程有任何疑问或者有想了解的内容,而我暂时没有写到的,也欢迎随时来找我聊聊。#头条创作挑战赛#
2023年12月07日
0 阅读
0 评论
0 点赞
2023-12-07
学会了吗(好用的javaide)java最好的ide,身为Java初学者的你,这些IDE的优缺点你都知道吗?,editplus java,
如今的Java可是个很好的编程语言,不仅本身功能强大,而且还能够适应多平台开发,于是市场上各种关于Java的开发工具都纷纷冒出头。那么,身为Java初学者的你,它们的优缺点你都知道吗?本文千锋武汉Java培训小编就列举6款常用的IDE的优缺点,看看哪一个更适合你。1:eclipse 这是应用比较广泛的一款针对于Java的IDE,其本身是一个框架平台。但是支持很多的插件,如C++和Python的,它可以及时检查以及纠正你代码中的错误,并且你只需点下鼠标就可以完成编译运行,非常适合新手上手,而且是完全免费的。但是因为其启动速度较慢,而且运行的时候非常占用内存,因此可能会出现卡顿的问题。2:Myeclipse很多初学者分不清Myeclipse和eclipse的区别,这里要说明:Myeclipse主要针对JavaEE开发,而eclipse主要针对Java。Myeclipse本来是eclipse下的一个插件,后来因为发展的比较快,自己已经能够独当一面了。它的好处就在于:一下载过来,在使用的时候就能够直接调用了,不需要像eclipse那样再调用插件。不过缺点很明显,大多数的Myeclipse是收费的,并且使用的范围比较小,大多数Java工作者只有在做JavaEE项目的时候才会选择这个。3:Idea全称为IntelliJ IDEA,它是业界公认的最好的开发Java的IDE之一。支持各类版本工具(SVN、Github、git等)、而且在代码重构、代码提示、J2ee支持方面更是超常的,分为免费版和旗舰版,旗舰版优点很明显,还支持MySQL、PHP、Python等,免费版只支持少数语言,但是Java正好在此列。4:EditPlus其本身是一个带有编辑功能的可处理文本,虽然它占用的内存比较小,但是它的功能非常强大:因为其体积小,启动速度很快,支持中文,扩展性强,并且配置功能也很强大,界面非常美观整洁,而且支持代码折叠。但是其缺点也比较明显,它的代码自动完成的功能比较弱,而且没有代码提示功能,这对于刚上手的Java初学者并不是非常友好。5:Notepad++ 这个软件的优点非常多,首先,Notepad++这款软件是完全免费使用的,而且支持宏。其次。还支持一些扩充功能的外挂模组!支持目前所有主流的计算机编程语言。但是其有一些问题,比如在写HTML的时候,当光标放在/的时候,标签会突出显示。读取一些文档的时候,会读不出tab过的代码,致使代码格式非常之乱。对于一些强迫症的初学者有一些不友好。6:Visual Studio其有着领先于编程界的数据库工具,还有灵活的软件建模和高效的体系结构指导,并且自带测试功能,这对于很多的Java初学者来说,可以比较简单得发现Bug所在。但是其缺点也很明显,它的输出非常单调,错误信息需要一个个点开来看,不是非常方便,而且不带本地记录功能,而Java初学者平时并没有Ctrl+S的习惯。以上就是千锋武汉Java培训小编整理的几款IDE的优缺点。每一个Java工具都有着一些优缺点,需要一些初学者去取舍。那么,读者们,你认为那一个Java开发工具更加适合你呢?欢迎给小编留言分享!Java的学习任重而道远,如果你是零基础,建议你来千锋武汉Java培训。千锋武汉Java培训课程大牛讲师全程面授,全新打造“主流技术+前沿技术+企业级联动”教学课程,重新优化和定义JavaEE,采用最新版本技术开展教学,致力于为学员打造最牛的、最新的技术。严格的管理制度让你在五个月的时间成功蜕变成为一名合格的Java开发工程师,更有两周免费试听,让你提前亲身实地感受学习氛围。更多Java行业动态和学习资料,可以关注“武汉千锋”微信公众号。
2023年12月07日
0 阅读
0 评论
0 点赞
2023-12-07
学到了吗(java数据库jdbc)jdbc数据库连接步骤,数据库:JDBC详解,java dbase,
1.什么是JDBCJDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。2.数据库驱动 我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。其实也就是数据库厂商的JDBC接口实现,即对Connection等接口的实现类的jar文件。二、常用接口1.Driver接口Driver接口由数据库厂家提供,作为java开发人员,只需要使用Driver接口就可以了。在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序,不同的数据库有不同的装载方法。如: 装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");装载Oracle驱动:Class.forName("oracle.jdbc.driver.OracleDriver");2.Connection接口 Connection与特定数据库的连接(会话),在连接上下文中执行sql语句并返回结果。DriverManager.getConnection(url, user, password)方法建立在JDBC URL中定义的数据库Connection连接上。 连接MySql数据库:Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");连接Oracle数据库:Connection conn =DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password"); 连接SqlServer数据库:Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password"); 常用方法:createStatement():创建向数据库发送sql的statement对象。prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。prepareCall(sql):创建执行存储过程的callableStatement对象。setAutoCommit(boolean autoCommit):设置事务是否自动提交。commit() :在链接上提交事务。rollback() :在此链接上回滚事务。3.Statement接口 用于执行静态SQL语句并返回它所生成结果的对象。 三种Statement类:Statement:由createStatement创建,用于发送简单的SQL语句(不带参数)。PreparedStatement :继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,所以我们一般都使用PreparedStatement。CallableStatement:继承自PreparedStatement接口,由方法prepareCall创建,用于调用存储过程。 常用Statement方法:execute(String sql):运行语句,返回是否有结果集executeQuery(String sql):运行select语句,返回ResultSet结果集。executeUpdate(String sql):运行insert/update/delete操作,返回更新的行数。addBatch(String sql) :把多条sql语句放到一个批处理中。executeBatch():向数据库发送一批sql语句执行。4.ResultSet接口ResultSet提供检索不同类型字段的方法,常用的有:getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。getBoolean(int index)、getBoolean(String columnName):获得在数据库里是Boolean类型的数据。getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。 ResultSet还提供了对结果集进行滚动的方法:next():移动到下一行Previous():移动到前一行absolute(int row):移动到指定行beforeFirst():移动resultSet的最前面。afterLast() :移动到resultSet的最后面。使用后依次关闭对象及连接:ResultSet → Statement → Connection三、使用JDBC的步骤加载JDBC驱动程序 → 建立数据库连接Connection → 创建执行SQL的语句Statement → 处理执行结果ResultSet → 释放资源1.注册驱动 (只做一次) 方式一:Class.forName(“com.MySQL.jdbc.Driver”); 推荐这种方式,不会对具体的驱动类产生依赖。 方式二:DriverManager.registerDriver(com.mysql.jdbc.Driver); 会造成DriverManager中产生两个一样的驱动,并会对具体的驱动类产生依赖。2.建立连接 Connection conn = DriverManager.getConnection(url, user, password); URL用于标识数据库的位置,通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为: 其他参数如:useUnicode=true&characterEncoding=utf83.创建执行SQL语句的statement1 //Statement2 String id = "5";3 String sql = "delete from table where id=" + id;4 Statement st = conn.createStatement();5 st.executeQuery(sql);6 //存在sql注入的危险7 //如果用户传入的id为“5 or 1=1”,那么将删除表中的所有记录1 //PreparedStatement 有效的防止sql注入(SQL语句在程序运行前已经进行了预编译,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or 1=1也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令)2 String sql = “insert into user (name,pwd) values(?,?)”;3 PreparedStatement ps = conn.preparedStatement(sql); 4 ps.setString(1, “col_value”); //占位符顺序从1开始5 ps.setString(2, “123456”); //也可以使用setObject6 ps.executeQuery(); 4.处理执行结果(ResultSet)1 ResultSet rs = ps.executeQuery(); 2 While(rs.next()){ 3 rs.getString(“col_name”); 4 rs.getInt(1); 5 //…6 } 5.释放资源 //数据库连接(Connection)非常耗资源,尽量晚创建,尽量早的释放//都要加try catch 以防前面关闭出错,后面的就不执行了1 try {2 if (rs != null) {3 rs.close();4 }5 } catch (SQLException e) {6 e.printStackTrace();7 } finally {8 try {9 if (st != null) {10 st.close();11 }12 } catch (SQLException e) {13 e.printStackTrace();14 } finally {15 try {16 if (conn != null) {17 conn.close();18 }19 } catch (SQLException e) {20 e.printStackTrace();21 }22 }23 }四、事务(ACID特点、隔离级别、提交commit、回滚rollback)1.批处理Batch
2023年12月07日
0 阅读
0 评论
0 点赞
2023-12-07
速看(五千左右公路车整车推荐)5000元公路自行车推荐,"5000元以下的公路自行车推荐及评价",java veloce,
以下是对5000元以下的公路车的优缺点以及综合评价的介绍:(但只是我认为可买车型并不全面,以下观点仅代表个人看法)1. 捷安特 SCR2: 优点:轻量化设计,加速迅猛;舒适的乘坐姿势;坚固耐用的构造。 缺点:可能在长距离骑行时缺乏舒适性。2. 捷安特 ESCAPE2:优点:适用于多种道路条件;舒适的乘坐姿势;适合长距离骑行。 缺点:相对较重,可能在爬坡时会感到吃力。3. JAVA VELOCE: 优点:具有良好的操控性能;舒适的乘坐姿势。 缺点:可能在上坡时需要更多的努力。4. 闪电 SIRRUS 2.0: 优点:轻巧的设计;灵活的操控性能;良好的加速性能。 缺点:可能缺乏一些舒适性。5. 闪电 ALLEZ BASE: 优点:价格实惠;轻量化设计;适合入门级骑行者。 缺点:可能缺乏一些高级特性。6. 喜德盛 RF350D: 优点:强大的动力系统;适合长距离骑行;稳定性高。 缺点:可能相对较重;价格较高。7. 美利达斯特拉95D: 优点:舒适的乘坐姿势;适合长距离骑行;优秀的刹车性能。缺点:相对较重;需要额外的维护保养。8. 捷安特 Avail 3: 优点:专为女性设计,适合女性骑行者;舒适的乘坐姿势。 缺点:可能在某些方面的性能相对较低。根据您的需求,综合评价如下:- 如果您注重舒适性和多种道路条件的适应性,可以考虑捷安特 ESCAPE2。- 如果您注重轻量化和加速性能,可以选择闪电 SIRRUS 2.0。- 如果您是入门级骑行者或注重价格实惠,可以选择闪电 ALLEZ BASE。- 如果您需要强大的动力和适合长距离骑行的稳定性,可以考虑喜德盛 RF350D。- 如果您是女性骑行者,可以考虑捷安特 Avail 3。在购买之前最好试骑各款车辆,以确定最适合您个人需求的公路车。建议在1. 在线购物网站,2. 零售商官方网站,3. 当地自行车店等渠道进行购买请注意,价格可能因不同地区和销售商的区别而有所变动。建议您在购买前与多家销售商进行比较,并仔细权衡价格与产品品质、性能等因素。
2023年12月07日
0 阅读
0 评论
0 点赞
2023-12-07
学到了(java实现定时)java定时器开关怎么设置时间,避坑指南,Java中定时器Timer致命缺点,我差点就踩到了,java 延时10秒,
简介这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问。后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人没有问题,特别是正在看我博文的小伙伴那更不用说了!!给你们点个狂力赞。接下来就是学习方法了,我发现近期来咨询我问题的小伙伴学习姿势不对,所以我用Java中定时器Timer为案例整理下我的学习方法。万丈高楼平地起,所以我一贯的做法都是先用最简单,最简单,最简单案例先行!那就先来个Hello World吧!案例1:定时器打印Hello World!importjava.text.ParseException;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/*** @author :jiaolian* @date:Created in 2021-01-05 20:42*@description:Timer启动后内置线程不销毁* @modified By:* 公众号:叫练*/public class TimerThreadNoStopTest {//TimerTask为抽象类,继承TimerTask类必须要实现里面抽象方法private static class Task extends TimerTask {@Overridepublic void run() {System.out.println("hello world!");}}public static void main(String[] args) throws ParseException {Timer timer = new Timer();Task task = new Task();long currenTime = System.currentTimeMillis();//提交Task线程;程序按传入日期运行timer.schedule(task,new Date(currenTime));}}如上面程序代码,Timer提交了一个task任务并传入了currenTime当前时间,控制台马上打印了"hello world!",如果schedule传入的第二个参数是new Date(currenTime+2000)表示延迟2m执行task任务,这里简单使用方法就不过多的描述了,但是大家在学习过程中遇到疑惑的问题一定要多尝试多写代码测试,这是理解代码必不可少的一部分,不要以为能看懂就不写了,**像我在学习过程中,如果稍微有疑问,我会立马动手写代码测试,因为我知道有时候自己可能懂了,但那可能不是真正的懂,只有代码能检验出来!**下图是程序控制台打印结果。如果大家执行了你会发现一个问题,程序一直不结束运行,也就是程序不死。那是什么导致这样的结果呢?线程不死问题?原因分析:如下图所示,主线程执行Timer timer = new Timer();会创建了一个新的子线程timer,timer线程通过死循环来取队列里面的任务task[1],队列其实就是一个数组实现TaskQueue,队列里面如果没有任务,那timer线程就会一直等待直到主线程调用schedule提交任务,主线程就会将task加入到TaskQueue队列数组并通知timer线程执行任务并删除队列的第一个任务,如果是主线程提交的是定时任务,就会将任务重新加入队列,任务执行完毕后,如果此时队列为空,timer线程就会继续等待任务提交到队列,一直会循环上面的过程。如果想退出timer线程,可以调用cancel方法会退出死循环。线程不死原因是timer线程一直在等待主线程提交任务,timer线程和主线程通信是通过调用wait/notify实现。我们之前做生产者/消费者案例时详细介绍过,这里老铁不再重复叙述了,可以去翻看文章**《母鸡下蛋实例》**。这个过程中,我们发现timer是一个单线程,我是单线程怎么了?单线程也有错吗?思考个问题,如果timer这个单线程提交了两个任务怎么办?我们看下面代码!案例2:单线程问题import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/*** @author :jiaolian* @date:Created in 2021-01-06 10:53*@description:多任务执行测试,任务只能顺序执行;* @modified By:* 公众号:叫练*/public class MultTaskExecuteTest {private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");private static class MyTask1 extends TimerTask {@Overridepublic void run() {System.out.println("task1 begin:"+SIMPLE_DATE_FORMAT.format(new Date()));try {Thread.sleep(10000);} catch(InterruptedException e) {e.printStackTrace();}System.out.println("task1 end:"+SIMPLE_DATE_FORMAT.format(new Date()));}}private static class MyTask2 extends TimerTask {@Overridepublic void run() {System.out.println("task2 begin:"+SIMPLE_DATE_FORMAT.format(new Date()));System.out.println("task2 end:"+SIMPLE_DATE_FORMAT.format(new Date()));}}public static void main(String[] args){Timer timer = new Timer();MyTask1 myTask1 = newMyTask1();MyTask2 myTask2 =new MyTask2();long curTime = System.currentTimeMillis();System.out.println("当前时间:"+SIMPLE_DATE_FORMAT.format(curTime));timer.schedule(myTask1,new Date(curTime));//myTask1执行时间过长,myTask2 被执行时间会被延迟;timer.schedule(myTask2,new Date(curTime+1000));}}如上面程序代码,timer线程提交了两个任务myTask1,myTask2,myTask1任务会立刻执行,myTask2计划延迟一秒执行,myTask1执行过程中会休息10秒钟,我们观察任务执行时间如下图所示,myTask2任务是等待myTask1任务执行完毕后再执行的,其实myTask2只是延迟一秒执行,结果却延迟了10秒,说明了timer单线程会串行化任务导致myTask2延迟执行,所以**Timer是适合轻量级定时任务,如果设置大量任务,可能会存在延迟执行情况。定时器实际应用场景在日常系统开发中,相信你遇到过类似需要重复执行的任务,比如每天凌晨2点清理数据库某张表的垃圾数据,页面显示设备(服务器)运行状态也需要每隔3秒调用设备状态接口查询设备情况等,这些功能开发都需要用到定时器,当然Timer定时器也有自身的缺陷,比如它是单线程的,后面会说到线程池中的定时器是多线程的,可以优化Timer,所以掌握Timer定时器为后面学习高阶内容打好基础。知其然知其所以然,在实际应用中我们能得心应手!学习方法心得大家可以看到我最近几篇文章分析多线程花了不少精力都在谈论可见性,原子性,母鸡下蛋生成消费问题等问题,因为这些特性是理解多线程的基础,在我看来基础又特别重要,所以怎么反复写我认为都不过分,在这之前有很多新手或者有2到3年工作经验的童鞋经常会问我关于Java的学习方法,还有一大批童鞋一上来就要做springboot,ssm项目,我是不建议这么干的,你在做项目之前先要了解下servlet,mvc思想啊,这是基础。我给他们的建议就是要扎实基础,别上来就学高级的知识点或者框架,比如ReentrantLock源码,线程池框架,就像你玩游戏,一开始你就玩难度级别比较高的,一旦坡度比较高你就会比较难受吃力更别说对着书本了,这就是真正的从入门到放弃的过程。同时在学习的时候别光思考,觉得这个知识点自己会了就过了,这是不够的需要多写代码,多实践,你在这个过程中再去加深自己对知识的理解与记忆,其实有很多知识你看起来是理解了,但是你没有动手去实践,你****也没有真正理解,这样只看不做的方法我是不推荐的,本人本科毕业后工作7年,一直从事Java一线的研发工作,担任Java高级研发工程师,中间也带过团队,因为自己曾经踏着坑过来的,对学习程序还是有一定的心得体会,我会在今后的日子里持续整理把一些经验和知识方面的经历分享给大家,希望大家喜欢关注我。我是叫练,叫个口号就开始练!总结下来就是两句话:多动手,扎实基础,从简单做起,然后慢慢深入!总结我们用代码简述timer定时器提交任务,并说明了timer是单线程的适合轻量级的定时任务,这是它的缺陷。鉴于篇幅有限其中timer还有很多方法我们没有用代码贴出来,比如定时执行,延迟执行,timer取消方法,希望大家一一对着书本执行起来,给大家推荐本多线程入门学习书籍,《Java多线程编程核心技术》,书本以案例为主,也没有特别难理解的案例,非常适合新手学习。作者:叫练3491链接:https://juejin.cn/post/6915214654734073864来源:掘金
2023年12月07日
0 阅读
0 评论
0 点赞
1
2
...
290