Java启动线程的3种方法详解:Thread、Runnable与Lambda示例
你是不是刚学Java,面对“线程”这词儿就头皮发麻?别慌!今天咱们就用最接地气的方式,把Java启动线程的三大绝活掰开揉碎了讲明白。我刚开始学的时候也觉得这玩意儿玄乎,后来才发现其实就是一层窗户纸——捅破了就透亮!
一、最原始的招式:直接继承Thread类
(敲黑板)这是教科书里必讲的祖传方法,??extends Thread??这个操作就跟盖章似的,谁用谁知道。咱们直接上案例:
java复制// 举个卖票的例子 class TicketSeller extends Thread { private int tickets = 10; @Override public void run() { while(tickets > 0) { System.out.println(Thread.currentThread().getName() + "卖出了第" + tickets-- + "张票"); } } } public class Main { public static void main(String[] args) { new TicketSeller().start(); new TicketSeller().start(); } }
??重点来了:??
- 必须重写
run()
方法,这里头放你要干的活儿 - 调用
start()
而不是直接调用run()
(划重点!直接调用run就成普通方法了) - 每个Thread对象都是独立作战的士兵
不过啊,这方法有个硬伤——Java是单继承的!你继承了Thread就不能继承其他类了。这时候你可能会问:那我要继承其他类怎么办?别急,往下看!
二、灵活度爆表的玩法:实现Runnable接口
(拍大腿)这才是业界公认的正确打开方式!??implements Runnable??这招就像穿松紧裤——弹性十足还不勒肚子。咱们把刚才的卖票案例改造一下:
java复制class TicketWindow implements Runnable { private int tickets = 10; @Override public void run() { while(tickets > 0) { System.out.println(Thread.currentThread().getName() + "窗口卖出第" + tickets-- + "张票"); } } } public class Main { public static void main(String[] args) { Runnable task = new TicketWindow(); new Thread(task, "北京西站").start(); new Thread(task, "上海虹桥").start(); } }
??划重点对比:??
- ?? 可以继承其他类(终于不用在Thread一棵树上吊死了)
- ?? 多个线程共享同一个Runnable实例(像上面的票数就是共享的)
- ?? 更符合面向对象的设计思想(把任务和线程本身解耦)
不过我发现新手常掉这个坑:明明用了Runnable,为什么票数卖超了?这就是线程安全问题啦,咱们后面再说这个。
三、新时代的骚操作:Lambda表达式
(吹口哨)Java8带来的这个神器,简直是懒癌患者的福音!以前要写一坨代码,现在一行搞定。来看怎么用Lambda启动线程:
java复制public class LambdaThread { public static void main(String[] args) { // 终极精简版 new Thread(() -> { System.out.println("我在用Lambda飞起~"); }).start(); // 带参数的玩法 Runnable task = () -> System.out.println("连run都省了!"); new Thread(task).start(); } }
??为什么推荐这个:??
- 代码量直接砍半(程序员的手腕健康就靠它了)
- 不用定义单独的类(临时任务简直不要太方便)
- 看着就高大上(装X必备技能)
不过要提醒各位萌新:Lambda虽好,可不要贪杯哦!复杂逻辑还是老老实实用传统写法更清晰。
四、选哪个方法好?老司机掏心窝建议
这三种方法就像吃饭用的筷子、叉子、手抓——没有绝对的好坏,关键看场合:
- 临时小任务 → ??Lambda??(方便快捷)
- 需要资源共享 → ??Runnable??(灵活可靠)
- 简单测试 → ??Thread??(随手就来)
但有个血泪教训要分享:千万别在项目中无脑用Thread继承!我之前接手过一个老项目,满屏的Thread子类,改个需求就跟拆炸弹似的,生怕动了哪个线程...
五、躲开这些坑,你就能超越80%的新手
-
??start()和run()傻傻分不清??
(举个栗子)把start()换成run(),程序也能跑,但这就变成单线程了!好比本来要开五台收割机收麦子,结果变成一个人开五趟... -
??线程安全问题防不胜防??
就像十个人同时往一个存钱罐塞钱,不加锁的话,最后数目肯定对不上。解决方案要么加synchronized
,要么用原子类。 -
??线程池才是终极形态??
虽然今天没细讲,但提前剧透:直接new Thread就像每次吃饭都新买双筷子,用线程池才是正经人家的做法,省资源又高效。
个人观点时间
用了这么多年Java线程,我最想说的是:??不要为了炫技而写复杂代码??!见过有人非要把Lambda嵌套五层显示水平,结果三个月后自己都看不懂。代码首先是给人看的,其次才是给机器执行。
最后送大家一句话:线程不是洪水猛兽,把它想象成流水线上的工人,你当好包工头安排好任务就行。刚开始可能会被调度问题搞得头大,但多踩几次坑自然就开窍了。编程嘛,不就是bug叠着bug成长起来的?
本文由嘻道妙招独家原创,未经允许,严禁转载