读书也要记:Java 线程(基础)

近来读了好几篇“老马说编程”写的 Java 多线程文章,这里记录一下第一篇的摘要,以及拓展查找了点相关的东西,算是复习巩固(有些冷知识平时还真没留意过)。原文:(65) 线程的基本概念 / 计算机程序的思维逻辑

在 Java 中创建线程有两种方式,一种是继承 Thread,另外一种是实现 Runnable 接口。

extends Thread
  • 继承 Thread 的类,重载 run 方法,方法签名是固定的,public,没有参数,没有返回值,不能抛出 checked Exception (可以抛出unchecked Exception),下图帮大家复习一下两种 Exception

    checked & unchecked Exception

  • 调用 Thread 的 start 方法后,线程开始执行;如果不调用 start,run 的代码会在当前线程执行

  • 怎么确认在跑的那一个线程呢?

/**
     * Returns a reference to the currently executing thread object.
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();

难得看到 native 关键字,所以 Thread 是 JNI (Java Native Interface),略懵逼,哪位高人来指导下?

  • 线程 id 是递增的整数,线程name可以设置
    /* For generating thread ID */
    private static long threadSeqNumber;
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
implements Runnable
  • 仅仅实现 Runnable 是不够的,需要new Thread,启动线程都是调用 Thread 对象的 start 方法
程序什么时候退出,关于 daemon 线程
  • 启动线程会启动一条单独的执行流,整个程序只有在所有线程都结束的时候才退出
  • 但 daemon 线程是例外,当整个程序中剩下的都是 daemon 线程的时候,程序就会退出。
  • daemon 线程一般是其他线程的辅助线程,在它辅助的主线程退出的时候,它就没有存在的意义了。
  • Java 也会创建多个线程,除了 main 线程外,至少还有一个负责垃圾回收的线程,这个线程就是 daemon 线程,在 main 线程结束的时候,垃圾回收线程也会退出。
关于 Thread 的小知识
  • sleep():睡眠期间,该线程会让出CPU,但睡眠的时间不一定是确切的给定毫秒数,可能有一定的偏差。
  • yield():告诉操作系统的调度器,我现在不着急占用CPU,你可以先让其他线程运行。(想起 Python 的 yield 😄)
  • ** join()**:让调用join的线程等待该线程结束,比如希望main线程在子线程结束后再退出
public static void main(String[] args) throws InterruptedException {
    Thread thread = new HelloThread();
    thread.start();
    thread.join();
}  
  • 已经 deprecated 的方法
  • public final void stop()
  • public final void suspend()
  • public final void resume()

stop() 会引起线程涉及的 monitor 状态的不确定性,所以不建议被调用,那么怎么 stop 一个 Thread 啊,懵逼了吧。

The Answer: In Java there's no clean, quick or reliable way to stop a thread.
Instead, Threads rely on a cooperative mechanism called Interruption. This means that Threads could only signal other threads to stop, not force them to stop.

  • 一种办法是通过一个简单的 flag 变量来控制
public class Task implements Runnable {
    private volatile boolean isRunning = true;

    public void run() {
        while (isRunning) {
            //do work
        }
    }

    public void kill() {
        isRunning = false;
    }
}
  • 类似还有通过 interrupt 来中断线程
public class Task1 implements Runnable {
  public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                      // do work
           }
    }
}
// in other thread, call interrupt()
myThread.interrupt();
  • 如果run里面不判断 Thread.currentThread().isInterrupted() 直接执行 interrupt() 会怎样呢?哪位读者来回答一下 _

  • 多线程的共享变量

  • 不同执行流可以访问和操作相同的变量

  • 不同执行流可以执行相同的程序代码

  • 当多条执行流执行相同的程序代码时,每条执行流都有单独的栈,方法中的参数和局部变量都有自己的一份

  • [内存可见性] 多个线程可以共享访问和操作相同的变量,但一个线程对一个共享变量的修改,另一个线程不一定马上就能看到,甚至永远也看不到。原因:在计算机系统中,除了内存,数据还会被缓存在CPU的寄存器以及各级缓存中,当访问一个变量时,可能直接从寄存器或CPU缓存中获取,而不一定到内存中去取,当修改一个变量时,也可能是先写到缓存中,而稍后才会同步更新到内存中。

  • 多线程的成本

  • 创建开销(空间和时间):每个线程创建必要的数据结构、栈、程序计数器。

  • 线程切换开销(时间):上下文切换,这个切换不仅耗时,而且使CPU中的很多缓存失效,是有成本的。

  • 如果执行的任务都是CPU密集型的,那创建超过CPU数量的线程是没有必要的,并不会加快程序的执行。

  • IO密集型的,创建超过 CPU 核数的线程是会提高效率的(线程数到多少合适呢?Netty的源码里有相关的解说)


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

推荐阅读更多精彩内容

  • 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要...
    嘟爷MD阅读 7,302评论 21 272
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,559评论 18 399
  • 啊今天在家也同样高产~ 超喜欢执笔画线的感觉~ 啦啦啦啦啦啦~ 下面画的线稿子都是图片写生~ 我喜欢那双眼睛~ 小...
    小c桃o阅读 984评论 2 8
  • 如果有来生, 我愿做一只鸟。 飞上常埋于你的树杈上, 陪伴在你身旁, 终日为你歌唱, 不离不弃。 ...
    溪边渔人阅读 87评论 0 1
  • 殷墟,安阳最著名的景点,世界遗产,它是商朝后期都城的遗址,包括宫殿宗庙遗址和王陵区。这里的东西大致分三类:青铜器陶...
    寒塘渡鹤阅读 1,376评论 12 7