并发王者课-青铜01:牛刀小试-如何创建线程之初体验

欢迎来到《并发王者课》,本文是该系列文章中的第1篇

从本文开始,我将基于王者中的段位和场景,从青铜黄金铂金砖石星耀王者,不同的段位对应不同的难易程度,由浅入深逐步介绍JAVA中的并发编程,并在每周二、四、六持续更新。

在文章的知识体系方面,主要以实践为主,并在实践中穿插理论知识的讲解,而本文将从最简单的线程创建开始。

一、一个游戏场景

在本局游戏中,将有3位玩家出场,他们分别是哪吒、苏烈和安其拉。根据玩家不同的角色定位,在王者峡谷中,他们会有不同的游戏路线:

  • 作为战士的哪吒将走上路的对抗路线;
  • 法师安其拉则去镇守中路;
  • 战坦苏烈则决定去下路。

二、代码实现

显而易见,你已经发现这几个玩家肯定不是单线程。接下来,我们将通过简单的多线程模拟出他们的路线。当然,真实的游戏引擎中绝不会是几个简单的线程,情况会复杂很多。

public static void main(String[] args) {
        Thread neZhaPlayer = new Thread() {
            public void run() {
                System.out.println("我是哪吒,我去上路");
            }
        };
        Thread anQiLaPlayer = new Thread() {
            public void run() {
                System.out.println("我是安其拉,我去中路");
            }
        };
        Thread suLiePlayer = new Thread() {
            public void run() {
                System.out.println("我是苏烈,我去下路");
            }
        };
        neZhaPlayer.start();
        anQiLaPlayer.start();
        suLiePlayer.start();
}

代码的运行结果:

我是哪吒,我去上路
我是苏烈,我去下路
我是安其拉,我去中路

Process finished with exit code 0

以上,就是游戏中简单的代码片段。我们创建了3个线程表示3个玩家,并通过run()方法实现他们的路线动作,随后通过start()启动线程。它足够简单,然而这里有3个知识点需要你留意。

1. 创建线程

Thread neZhaPlayer = new Thread();

2. 执行代码片段

public void run() {
    System.out.println("我是哪吒,我去上路");
}

3. 启动线程

neZhaPlayer.start();

对于我们来说,创建线程并不是我们的目标,我们的目标是运行我们期望的代码(比如玩家的游戏路线或某个动作),而线程只是我们实现这一目标的方式。因此,在编写多线程代码时,运行指定的代码片段无疑是极其重要的。在Java中,我们主要有2种方式来指定:

  • 继承Thread并重写run方法;
  • 实现Runnable接口并将其传递给Thread的构造器。

三、线程创建的两种方式

1. 继承Thread创建线程

在上面的示例代码中,我们所使用的正是这种方式,只不过是匿名实现,你也可以通过显示继承:

public class NeZhaPlayer extends Thread {
    public void run() {
        System.out.println("我是哪吒,我去上路");
    }
}

此外,在Java以及更高的JDK版本中,你还可以通过lambda表达式简化代码:

Thread anQiLaPlayer = new Thread(() -> System.out.println("我是哪吒,我去上路"));

2. 实现Runnable接口创建线程

创建线程的第2种方法是实现Runnable接口。我们创建了NeZhaRunnable类并实现Runnable接口中的run方法,如下面代码所示。

public class NeZhaRunnable implements Runnable {
    public void run() {
        System.out.println("我是哪吒,我去上路");
    }
}

Thread neZhaPlayer = new Thread(new NeZhaRunnable());
neZhaPlayer.start();

从效果上看,两种方式创建出来的线程效果是一样的。那么,我们应该怎么选择?

建议你使用Runnable

对于这两种方法,孰优孰劣并没有明确的规定。但是,从面向对象设计的角度来说,推荐你用第二种方式:实现Runnable接口

这是因为,在面向对象设计中,有一条约定俗成的规则,组合优于继承(Prefer composition over inheritance),如果没有特别的目的需要重写父类方法,尽量不要使用继承。在Java中所有的类都只能是单继承,一旦继承Thread之后将不能继承其他类,严重影响类的扩展和灵活性。另外,实现Runnable接口也可以与后面的更高级的并发工具结合使用。

所以,相较于继承Thread,实现Runnable接口可以降低代码之间的耦合,保持更好的灵活性。关于这一原则的更多描述,你可以参考《Effective Java》。

当然,如果你对Thread情有独钟,当我没说。此外,在Java中我们还可以通过ThreadFactory等工具类创建线程,不过本质上仍是对这两种方法的封装。

四、注意,别踩坑!

线程的启动固然简单,然而对于一些新手来说,在启动线程的时候,一不小心就会使用run()而不是start(),就像下面这样:

Thread neZhaPlayer = new Thread(new NeZhaRunnable());
neZhaPlayer.run();

如果你这么调用的话,你仍然可以看到你期望的输出,然而这正是陷进所在!这是因为,Runnable中的run()方法并不是你所创建的线程调用的,而是调用你这个线程的线程调用的,也就是主线程。那为什么直接调用run()方法也能看到输出呢?这是因为Thread中的run()会直接调用target中的run():

public void run() {
    if (target != null) {
        target.run();
    }
}

所以你看,如果你直接调用run()的话,并不会创建新的线程。关于这两个方法的执行细节,会在后面的线程状态中分析,这里你要记住的就是启动线程调用的是start(),而不是run()

以上就是文本的全部内容,恭喜你又上了一颗星✨

夫子的试炼

用两种不同的方式,创建出两个线程,交差打印1~100之间的奇数和偶数,并断点调试。

关于作者

关注公众号【技术八点半】,及时获取文章更新。传递有品质的技术文章,记录平凡人的成长故事,偶尔也聊聊生活和理想。早晨8:30推送作者品质原创,晚上20:30推送行业深度好文。

如果本文对你有帮助,欢迎点赞关注监督,我们一起从青铜到王者

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容