Java | 线程和进程,创建线程

一、线程与进程

线程定义

进程中执行的一个代码段,来完成不同的任务

组成:线程ID,当前指令指针(PC),寄存器集合(存储一部分正在执行线程的处理器状态的值)和堆栈

进程定义

执行的一段程序,一旦程序被载入到内存中准备执行就是一个进程

组成:文本区域(存储处理器执行的代码)、数据区域(存储变量和进程执行期间的动态分配的内存)和堆栈(存储着活动过程调用的指令和本地变量)

例如Windows系统中运行的一个exe就是一个进程

进入任务管理器,可以查看系统运行的进程,以及每个进程中的线程数

线程与进程的关系

1.  进程是系统内存分配的最小单位,线程是系统调度的最小单位

进程拥有自己的内存空间,因为线程是属于进程的,多线程直接共享该进程中内存,提高了程序的运行效率

2.  一个程序至少有一个进程,一个进程中包括一条 or 多条线程,线程不能独立于进程

在Java中,每次程序运行至少启动2个线程:一个是main线程,一个是垃圾收集线程。因为每当使用 Java 命令执行一个类时,都会启动一个JVM,每一个 JVM 实际上就是在操作系统中启动了一个进程

3.  进程与线程都可以并发执行

问题:如何了解 “并发” 执行 ,它与 “并行”执行一样吗?

并行执行:从宏观和微观的角度,都是同时执行的

并发执行:从宏观角度,似乎是同时执行;但从微观角度,不是同时执行

操作系统采取时间片的机制,使多个进程(线程)快速切换执行,在宏观上就有并行执行的错觉

在单核情况下,不存在并行执行;但在多核情况下,进程(线程)分布在不同的CPU中,可以并行执行程序

二、线程的生命周期

线程是一个动态执行的过程

1.  新建状态 New

创建线程对象,进入新建状态,此时线程属于 not  alive,直到执行 start()

创建线程: 使用 new 关键字和 Thread 类或其子类, 例如:Thread   t  = new  MyThread();

2.  就绪状态 Runnable

调用线程对象的 start() 方法,进入就绪状态,此时线程属于 alive ,但还未进入执行,只是做好了被 CPU 调度的准备

3.  运行状态 Running

当线程获取到CPU,进入运行状态,线程的 run() 方法才开始被执行,此时线程属于 alive

只有当线程处于就绪状态,才能被CPU调度,所以就绪状态是运行状态的唯一入口

4.  阻塞状态 Blocked

处于运行状态的线程,由于某种原因,放弃使用CPU,停止运行,进入阻塞状态,此时线程属于 alive

同步阻塞

同步锁 synchronized,当某线程占有了该同步锁, 则其他线程就不能进入到同步锁中,则这些线程就会进入阻塞状态

当在阻塞队列的线程获取到同步锁时,才能进入到就绪状态等待被调度

等待阻塞:(理解得有点绕)

调用线程的 wait() ,线程进入等待状态,此时会释放占用的 CPU 资源和锁(wait()方法需要在锁中使用)

当被其他线程调用 notify() 唤醒之后,需要重新获取对象的锁,所以会先进入Blocked状态,才会进入就绪状态

其他阻塞

调用线程的 sleep() 或 join() 或 发出了I/O请求,线程会进入到阻塞状态

当 sleep() 状态超时、join() 等待线程终止或者超时、或者 I/O 处理完毕时,线程重新进入就绪状态

5.  死亡状态 Dead

当一个线程的 run() 方法运行完毕 or 被中断 or 被异常退出,该线程进入死亡状态

三、线程的创建

-   实现 Runnable 接口,实例化 Thread 类(线程无返回值)

-   继承 Thread 类,重写 Thread 的 run() 方法(线程无返回值)

-   实现 Callable 接口,通过 FutureTask 包装器创建线程(线程有返回值)

1.  实现 Runnable 接口,实例化 Thread 类(线程无返回值)

step1:  创建一个类,例如 RunnableThread,实现 Runnable 接口

step2:  实例化 RunnableThread 对象, 创建 Thread 对象,将 RunnableThread 作为参数传给 Thread 类的构造函数,然后通过 Thread.start() 方法启动线程

运行结果

问题: 为什么创建 RunnableThread 对象后,需要将它和 Thread 对象进行关联?

查看 Runnable 接口的源代码,可以看到 Runnable 接口只有一个 run() 方法,所以需要通过 Thread 类的 start() 方法来启动线程

启动线程后,Thread 类中的 run() 方法会先判断传入的 target Runnable 对象的 run() 方法是否为空,若不为空,则调用 target Runnable 对象的 run() 方法

而且,RunnableThread 类实现 Runnbale 接口中不能直接使用 Thread 类中的方法,需要先获取到Thread 对象后,才能调用 Thread 方法

2.  继承 Thread 类,重写 Thread 的 run() 方法(线程无返回值)

step1:  创建一个类,例如 MyThread,继承 Thread 类,重写 Thread 的 run() 方法

step2:  实例化 MyThread 对象,直接调用 start() 方法启动线程

运行结果

问题:实现 Runnable 接口 和 继承 Thread 类,运行结果不一样,这是为什么?

继承 Thread 类和实现 Runnable 接口实现多线程,会发现这是两个不同的实现多线程

继承 Thread 类是多个线程分别完成自己的任务

实现 Runnable 接口是多个线程共同完成一个任务,其实用继承Thread类也可以实现,只是比较麻烦

这样的话,实现 Runnable 接口比继承 Thread 类具有一定的优势

1)适合多个相同的程序代码的线程去处理同一个资源

2)可以避免 Java 中的单继承的限制

当一个类继承 Thread 类后,则不能在继承别的类,而接口比较灵活,可以实现多个接口,而且实现接口了还可继续继承一个类

3)增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

参考链接:https://www.cnblogs.com/CryOnMyShoulder/p/8028122.html

                 https://www.cnblogs.com/xubiao/p/5418141.html

3.  实现 Callable 接口,通过 FutureTask 包装器创建线程(线程有返回值)

step1:  创建一个类,例如 CallableThread,实现 Callable 接口,重写 Callable 接口的 call() 方法

step2:  实例化 CallableThread 对象,使用 FutureTask 类来包装 CallableThread 对象

然后 FutureTask 对象作为参数传给 Thread 类的构造函数,通过 Thread.start() 方法启动线程

使用 FutureTask.get() 得到 Callable 接口的 call() 方法的返回值

返回结果

Callable 和 Runnable 相似,类实例都需要被 Thread 执行,但 Callable 接口能返回一个值或者抛出一个异常,Runnable 不能

实现 Callable 接口需要重写其唯一的 call() 方法

FutureTask 实现了 Runable 接口 和 Future 接口,所以如果想 Callable 实例作为 Thread 的执行体就必须通过 FutureTask 来作为桥梁


参考链接:https://www.cnblogs.com/ganchuanpu/p/7704468.html

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

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,099评论 0 23
  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    小徐andorid阅读 2,805评论 3 53
  • 单任务 单任务的特点是排队执行,也就是同步,就像再cmd输入一条命令后,必须等待这条命令执行完才可以执行下一条命令...
    Steven1997阅读 1,176评论 0 6
  • 线程概述 线程与进程 进程  每个运行中的任务(通常是程序)就是一个进程。当一个程序进入内存运行时,即变成了一个进...
    闽越布衣阅读 1,009评论 1 7
  • 上回讲到,用户端如何派单,今天要讲的,是派单完成后,生成订单的界面,及支付输入密码的页面设计。 我的订单可...
    一盒甜豆奶_阅读 259评论 0 3