了解Java中的多线程

1. 线程与并发

1.1. 理解线程与进程的区别(了解)

进程:是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程(1,n)。比如在Windows的任务管理器中,一个运行的xx.exe就是一个进程。

线程:是指进程中的一个执行任务(控制单元),一个进程中可以运行多个线程,多个线程可共享数据。

多进程:操作系统中同时运行的多个程序。

多线程:在同一个进程中同时运行的多个任务。

一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个控制单元,这就是多线程。

1.2. 主线程 main(了解)

在运行一个简单的Java程序的时候,就已经存在了两个线程,一个是主线程,一个是后台线程——维护的垃圾回收。主线程很特殊,在启动JVM的时候自动启动的。

1.3. 线程的创建和启动(掌握)

方式一,继承Thread类:

  • 自定义类继承Thread

  • 覆写run方法

  • 创建自定义类对象

  • 自定义类对象调用start方法

class MyThread extends Thread {

    public void run() {

        //线程体,线程启动时,会自动调用本方法,所有这里是我们写代码的主体部分

    }

}

public class ExceptionDemo {

    public static void main(String[] args) {

        MyThread t = new MyThread();

        t.start();//调用Thread的start方法,JVM会自动调用run方法。

    }

}

方式二,实现Runnable 接口

  • 自定义类实现Runnable接口

  • 覆写run方法

  • 创建自定义类对象

  • 把自定类的对象作为Thread类构造器参数,并调用Thread对象start方法

class MyRunnable implements Runnable {

    public void run() {

        //线程体,线程启动时,会自动调用本方法,所有这里是我们写代码的主体部分

    }

}

public class ThreadDemo2 {

    public static void main(String[] args) {

        MyRunnable target = new MyRunnable();

        Thread t = new Thread(target);

        t.start();

    }

}

第一种使用起来方便,启动一个线程也方便,很多功能都在Thread类中定义好了;

第二种方式启动得依赖于Thread,因为本身Runnable中只有run方法,请看Thread的构造方法。

1.3.1. 线程体-run方法(掌握)

不管哪种方式创建的线程,都得覆写run 方法,因为这是线程体方法,该方法在线程启动之后会自动被调用。

public void run() {

    //线程体,线程启动时,会自动调用本方法,所有这里是我们写代码的主体部分

}

线程的执行随机性:

一旦一个线程启动之后就是一个独立的线程,等待CPU的调度分配资源,不会因为启动它的外部线程结束而结束。

class MyThread extends Thread {

    public void run() {

        //自定义线程中的for循环打印i,打印顺序是完全随机的。

        for (int i = 0; i < 10; i++) {

            System.out.println("MyThread  ==> " + i);

        }

    }

}

public class Demo {

    public static void main(String[] args) {

        MyThread mt = new MyThread();

        mt.start();

        //主线程中的for循环打印i

        for (int i = 0; i < 10; i++) {

            System.out.println("main  ==> " + i);

        }

    }
    
}

多次运行该程序,观察每次运行的结果。

1.3.2. 线程的启动(掌握)

启动线程必须调用线程类Thread中的start方法,该方法应该由Thread类的一个实例来调用,下面是方法签名:

public void start() 

底层会调用该线程的 run 方法。

只有调用了线程对象的start方法才会开启一个新的线程,如果是直接调用对象的run方法不会开启新的线程,只是一个单线程。

注意:启动一个新线程,不能使用run()方法,只能使用start方法。

1.4. 线程生命周期和状态(掌握)

image.png
  • 新建:当程序使用new创建一个线程后,该线程处于新建状态,此时他和其他java对象一样,仅仅由Java虚拟机为其分配内存并初始化成员变量值。

  • 可运行状态:RUNNABLE状态实际上可细分成两种状态,READY和RUNNING。分别表示就绪状态和运行状态。

    • 就绪状态:当线程对象调用start()方法后,该线程处于就绪状态,进入线程队列排队。此时该状态线程并未开始执行,仅表示可以运行了。至于该线程何时运行,取决于CPU调度器的调度。

    • 运行状态:表示某线程对象被CPU调度器的调度,执行线程体。就绪状态和运行状态是可以相互切换的,切换的原因依旧参照CPU调度器调度了哪一个线程。

  • 阻塞状态:正在运行的线程遇到某个特殊情况如,同步、等待I/O操作完成等。 进入阻塞状态的线程让出CPU资源,并暂时停止自己的执行。

  • 等待状态:有时一个可运行状态线程转变成等待状态,它会等待另一个线程来执行一个任务,一个等待状态的线程只有通过另一个线程通知它转到可运行状态,才能继续执行。

  • 计时等待状态:进入等待状态的线程如果没有其他线程对象来唤醒它,那么该线程对象将一直等待下去,此时我们可以考虑设计一个类似于闹钟一样的提示器,该提示器会在等待特定时间段之后唤醒该线程对象。

  • 终止状态:即死亡状态,表示线程终止。当线程成功执行完成或线程抛出未捕获的Exception或Error或调用线程的stop方法(易导致死锁,不推荐)。

1.5. 操作线程的方法(掌握)

1.5.1. join方法(了解)

join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。

比如在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。

1.5.2. sleep方法(了解)

sleep方法让正在执行的线程暂停一段时间,进入阻塞状态,常常用来模拟网络延迟等。

sleep(long milllis) throws InterruptedException:毫秒为单位

调用sleep()后,在指定时间段之内,该线程不会获得执行的机会

1.5.3. 线程的优先级(了解)

每个线程都有优先级,优先级的高低只和线程获得执行机会的次数多少有关。并不是说优先级高的就一定先执行,哪个线程的先运行取决于CPU的调度;

Thread对象的setPriority(int x)和getPriority()用来设置和获得优先级。

1.5.4. 后台线程(了解)

所谓后台线程,一般用于为其他线程提供服务。也称为守护线程。JVM的垃圾回收就是典型的后台线程。

特点:若所有的前台线程都死亡,后台线程自动死亡。

Thread对象setDaemon(true)用来设置后台线程。

setDaemon(true)必须在start()调用前,否则抛IllegalThreadStateException异常。

若要获得最好的学习效果,需要配合对应教学视频一起学习。需要完整教学视频,请参看https://ke.qq.com/course/272077

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

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,099评论 0 23
  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    小徐andorid阅读 2,805评论 3 53
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,955评论 1 18
  • 单任务 单任务的特点是排队执行,也就是同步,就像再cmd输入一条命令后,必须等待这条命令执行完才可以执行下一条命令...
    Steven1997阅读 1,176评论 0 6
  • 感觉很长时间没有写简书了,因为女儿也很长一段时间都表现的特别好。没有写简书,感觉总像有什么事情没有完成一样,让我牵...
    爱与信阅读 105评论 0 1