java中的线程和进程,Java | 线程和进程,创建线程

一、线程与进程

线程定义

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

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

进程定义

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

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

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

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

5ddcc068d177

线程与进程的关系

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

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

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

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

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

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

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

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

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

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

二、线程的生命周期

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

5ddcc068d177

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 接口

5ddcc068d177

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

5ddcc068d177

运行结果

5ddcc068d177

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

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

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

5ddcc068d177

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

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

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

5ddcc068d177

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

5ddcc068d177

运行结果

5ddcc068d177

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

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

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

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

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

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

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

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

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

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

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

5ddcc068d177

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

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

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

5ddcc068d177

返回结果

5ddcc068d177

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/399099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maven的pom报错的解决方法

如果在MyEclipse里面导入项目,导入不了,如下图 接下来可以点击Import Maven Projects里的Action那一行Resolve Later. 点击Do Not Execute(add to pom)就可以正常导入了转载于:https://www.cnblogs.com/JimmySeraph/p/8068299.html

django零开始

2019独角兽企业重金招聘Python工程师标准>>> 安装。。。后查看 import django django.VERSION #输出版本号,目前自己是py2.7.9和django1.8 1,新建一个django-project django-admin.py startproject project-name 一个project一般为一个项目 …

关于Python3.6下登陆接口的尝试

编者按:README:此代码为用户登陆界面,添加了寻求帮助选项。1.学习了基本数据类型,string, int,以及while循环,continue, break, if, elif, else条件语句,“x".format(x)变量替代…

php 命令安装tp5,tp5.1框架的下载与安装方法步骤(图文)

大家可以都知道啊,tp框架5.1之前的版本都是可以在thinkphp的官网进行下载压缩包来安装框架的,那么在从tp5.1开始啊,就取消了下载压缩包安装的方法,那么我们如何进行下载呢?tp5.1的手册中开始就有提到tp5.1框架有两种安…

[连载]《C#通讯(串口和网络)框架的设计与实现》- 13.中英文版本切换设计

目 录 第十三章 中英文版本切换设计... 2 13.1 不用自带的资源文件的理由... 2 13.2 配置文件... 2 13.3 语言管理类... 3 13.4 应用管理类... 12 13.5 小结... 12 第十三章 中英文版本切换设计 13.1 不用自带的资源文件…

Mybaitis JdbcType 和javaType

2019独角兽企业重金招聘Python工程师标准>>> MyBatis 通过包含的jdbcType类型 BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINEDTINYINT REAL VARCHAR BINARY BLOB NVARCHARSMALLINT DOUBLE …

php数据趋势曲线,数据曲线图怎么做

数据曲线图怎么做?1、在电脑桌面上,新建一个excel文件(操作过程即为点击右键,在选项中选择“新建”选项,然后再选择“excel文件”,即可成功新建excel文件了)2、双击将新建的excel文件打开,输入你需要统计制…

ceph 分布式存储安装

[rootlocalhost ~]# rm -rf /etc/yum.repos.d/*.repo 下载阿里云的base源 [rootlocalhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo [rootlocalhost ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/r…

STM32学习之路-SysTick的应用(时间延迟)

开发板:奋斗V5 好~ 菜B要来搞实验了.. 前面已经说了SysTick的工作原理什么的了,这里就不说了.. 先来做第一个实验: 盗自奋斗的样例,嘿嘿, 用SysTick产生1ms的基准时间,产生中断,每秒闪烁一次(LED1 V6) (1)外围时钟初始化&#xf…

凡事预则立(Beta)

听说——凡事预则立 吸取之前alpha冲刺的经验教训,也为了这次的beta冲刺可以更好更顺利地进行,更是为了迎接我们的新成员玮诗。我们开了一次组内会议,进行beta冲刺的规划。 上一张我们的合照: 具体会议议程如下: 1、讨…

用Vue.js开发一个电影App的前端界面

我们要构建一个什么样的App? 我们大多数人使用在线流媒体服务(如Netflix)观看我们最喜欢的电影或者节目。这篇文章将重点介绍如何通过使用vue.js 2 建立一个类似风格的电影流媒体WEB交互界面(见上图)。 最终的产品可以…

eclipse 函数折叠展开

为什么80%的码农都做不了架构师?>>> 一、eclipse 代码块折叠显示 核查是否开启折叠功能全局folding(window->preference->Gerneral->Editor-Structured Text)右侧Appearance 勾选Enable folding检测对应源编辑(java/javaScript&…

mysql 引擎 校对,MySQL 字符集和校对

字符集是指一种从二进制编码到某类字符符号的映射,校对是一组用于某个字符集的排序规则。每一类编码字符都有其对应的字符集和校对规则MySQL 如何使用字符集每种字符集都可能有多种校对规则,并且都有一个默认的校对规则。每个校对规则都是针对某个特定的…

【研究】Metasploit自动攻击模块

环境:kali-linux-2017.3-vm-amd64 一、安装postgresql数据库 apt-get install postgresql apt-get install rubygems libpq-dev apt-get install libreadline-dev apt-get install libssl-dev apt-get install libpq5 apt-get install ruby-dev apt-get install lib…

让nginx支持thinkphp rewrite模式

为什么80%的码农都做不了架构师?>>> Nginx环境在Nginx低版本中,是不支持PATHINFO的,但是可以通过在Nginx.conf中配置转发规则实现:在nginx配置文件中添加 location / { if (!-e $request_filename) { rewrite ^(…

WPS怎样设置多级标题(如四级标题)

WPS期初,乍一看最多只能设置三级标题。 怎样设置四级以上标题呢? 这里以设置四级标题为例: 点击‘视图’->大纲, 假如,现在2.3.3这一行是三级标题: 在下拉框里选择‘4级’就可以了。 现在可以回到普通页面上&#x…

matlab实现主成分分析(遥感图像处理)

数据说明:采用的数据源是从别人那里拷的2012年全年的Sea Surface Temperature(海标温度,SST)数据,一直想找一份比较好的主成分分析数据,也没找到。 Matlab自身有主成分分析的函数princomp,其中返…

SQL Server中关于跟踪(Trace)那点事

前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案。 简单的举几个应用场景…

php怎么获取用户所在地址,php获取客户端ip及获取ip所在地址

// 获取ipfunction ip(){if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))$ip $_SERVER["HTTP_X_FORWARDED_FOR"];else if (isset($_SERVER["HTTP_CLIENT_IP"]))$ip $_SERVER["HTTP_CLIENT_IP"];else$ip $_SERVER["REMOTE_ADDR&…

php若$a没定义默认是,PHP之错误处理详解

PHP之错误处理详解错误报告PHP程序的错误发生一般归属于下列三个领域:1、语法错误语法错误最常见,并且也容易修复。如:代码中遗漏一个分号。这类错误会阻止脚本的执行2、运行时错误这种错误一般不会阻止PHP脚本的执行,但会阻止当前…