Java:进程:进程和线程的理解

进程和线程的区别:

答:线程是指进程内的一个执行单元,也是进程内的可调度实体。与进程的区别:

(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行。

(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

-----------------------------------------------------------------------------------------------------------------------------

 

在现代操作系统中,线程是真正执行计算机操作的东西,真正在操作电脑的不是应用程序,不是进程,而是线程。

线程,是一个基本单位,执行操作的,是线程。

应用程序与进程里面,有很多线程,像负责人机交互的窗口,它主要由 GUI 线程来控制的。

Java:进程:进程和线程的理解_第1张图片

以 IE 浏览器为例,即便你只开启一个页面,你也会发现,这个浏览器程序有非常多的线程,随着打开的标签和加载项越多,它所创建的线程也就越多。

其实你的电脑每个程序都至少有一个主线程,那个管理器中的每一个进程,其实内部包含若干线程,每个时间点都是某个程序进程中的某个线程在运行。

线程

     我们先看看维基百科对线程的定义:线程(英语:thread)是操作系统能夠進行運算调度的最小單位。它被包含在进程之中,是行程中的實際運作單位。一条线程指的是进程中一个单一顺序的控制流,一個进程中可以並行多個线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。此外,从资源分配的角度看,进程是资源所有资源分配的基本单位,线程则是CPU调度的基本单位,即使在单线程进程中也是如此。

 

引入线程的原因:

1)  一个应用程序中同时存在多个任务,其中的部分活动会随时间的推移而阻塞,而另外一部分则不会,例如,一个文字处理软件,前台部分需要从终端设备获得输入或者将处理完的部分输出,而后台线程则可以实现对文字的处理。故对于CPU密集型进程,该用多线程其性能不一定能得到很大提高,但对于IO密集型进程,其性能可得到很大提高。

2)  线程比进程更轻量级,创建和撤销的代价小,在许多系统中,创建一个线程比一个进程要快10~100倍不等。

3)  在多核CPU中,真正的并行有了可能。即在多线程设计中一部分可用来处理前台任务,一部分可用来处理后台任务,实现真正意义上的并行。

4)    线程间的切换代价要比进程切换的代价小。

 

引入多线程的原因:

 

1)某个操作可能会陷入长时间等待,等待的线程会进入睡眠状态,无法继续执行。多线程执行可以有效利用等待时间。如等待网络响应可能需要几秒的时间。

2)某个操作(常常是计算)会消耗大量的时间,如果只有一个线程,程序和用户之间的交互会中断。多线程可以让一个线程负责交付,另一个线程负责计算。

3)多CPU或者多核计算机,本身具备同时执行多个线程的能力,故单线程无法完全发挥计算机的计算能力。

4)相对于多进程应用,多线程在数据共享方面效率要高很多。

5)程序逻辑本身就要求并发操作。

 

现在我们通过考察一个例子,就可以更清楚看出多线程的有益之处了。

    假设用户正在编辑一本书。对于编辑这来说,最容易的办法是把正本书作为一个文件,便于编辑;而对于计算机来说把每个章节作为一个文件处理起来更快,但对于编辑者来说修改就太麻烦了,因为有的修改不止设计一个章节而是整本书,例如在整本书中替换某个词或字等等,如果整本书作为一个文件,正样处理就方便多了。否则,就得对每个章节所在文件进行处理。

     现在如果用在一个1000页的文档中删除第一页的某一行的某个词,为保证格式的正确性,字处理软件需要对文档进行格式处理。但此时用户需要立刻跳到地800也进行另外一处修改,于是字处理软件被强制对整个书的前800页进程格式处理,因为在排列该页前面的所有页面之前,字处理软件并不知道第800页的第一行应该在哪里。而在第800也的页面可以显示在屏幕之前,计算机可能要拖延想当长一段时间进行处理,从而令用户不甚满意。

此时,多线程便可以有用武之地了。假设字处理软件编写成含有两个线程的程序。一个线程处理用户的交互,另一个用来在后台进行格式处理。一旦第一页发生的修改,交互线程就立即同时后台格式处理线程重现整理整本书的格式。同时,交互式线程继续监控用户的鼠标、键盘,并响应诸如第一页之类的简单命令,此刻,后台线程正在进行疯狂的运算,如果运气好的话,格式整理可能在用户请求查看第800页之前完成,这样用户就感觉不到延迟了。

同理,为保证用户的编辑工作得到及时保存,可以在添加一个现场周期性对文件进现场可以处理磁盘备份,而不必干扰其他两个线程。拥有三个线程的情形如图2所示。

图2 三个线程的字处理软件

试想,如果是单线程的话,那么在进行磁盘备份的时,来自键盘或者鼠标的命令就会被忽略,直至备份完成。有的同鞋会说,可以引入中断机制来中止备份操作,相应鼠标和键盘的命令,但其复杂性可想而知。如果引入三个线程,其设计就简单多了,一个线程用于与用户交互,第二线程在得到地一个线程的通知后在后台进行文档的格式化处理,第三个线程则周期性将ARM内的内容被封到磁盘。

此处,很显然,这里用三个不同的进程是不能工作的,因为三个线程都需要在同一个文件上进行操作,通过三个线程,由于一个进程内的所有线程共享公共内存,于是便可以在同一文件上进行处理。同理,其他的交互式程序也可以采用同样的设计方法。

      看完这个例子,部分对多道程序设计比较忠心的同学可能会问,上述三个线程能协同完成工作,主要的便利之处在于其共享了进程中的公共内存空间。同样,也可以采用进程通信的方式来协同完成工作?答案确实如此,但仔细思考几个问题:1、进程通信与线程通信的代价孰高孰第?2、进程切换和线程切换的代价?3、如何保证三个进程所处理内容的一致性?而多线程方案中由于都是对同一文档内容进行处理,其一致性的保证则简单很多。如果能准确解答上述几个答案,为什么不选择多道程序设计方案来完成其上述工作的原因就不攻自破了吧。

线程的内容我们回顾差不多了,现在我们来一起看看进程与线程的关系和区别吧。

进程与线程:

     进程是操作系统的管理单位,而线程则是进程的管理单位;一个线程至少包含一个执行线程。不管是在单线程还是多线程中,每个线程都有一个程序计数器(记录要执行的下一条指令),一组寄存器(保存当前线程的工作变量),堆栈(记录执行历史,其中每一帧保存了一个已经调用但为返回的过程)。虽然线程寄生在进程中,但与他的进程是不同的概念,并且可以分别处理:进程是系统分配资源的基本单位,线程时调度CPU的基本单位。

     多线程是对多进程的模拟。前者,多个线程共享同一个地址空间和其他资源,后者共享物理内存、磁盘、IO等其他资源,故线程被称为“轻量级进程”。多线程在但CPU系统中运行时,线程轮流运行,犹如多道程序设计,制造线程并行运行的假象。在一个有三个CPU密集型的进程中,实际上每个线程在一个CPU上得到的真实CPU速度的三分之一。不过随着技术的发展,目前主流的CPU都已经直接硬件支持多线程,并允许线程在几个纳秒级内完成切换。后续会对多进程、多线程、以及多核之间的关系进行总结。

      线程间不像进程之间那样存在很大的独立性,一个进程的多个线程共享进程内部的很多资源,线程间可以互写对方的堆栈,而不同的进程则无法对其他进程的地址空间进行写操作。因此,在实现多线程编程中,应设计合理的同步通信机制,避免数据冲突的现象发生。图3给出了进程、线程的内容,其中进程的内容是该进程的所有线程共享的。

每个进程中的内容

每个线程中的内容

地址空间

程序计数器

全局变量

寄存器

打开文件

堆栈

子进程

状态

即将发生的报警

 

信号与信号处理程序

 

账户信号

 

同步、互斥信号量

 

原文参考:https://blog.csdn.net/u012398362/article/details/51475213

 

多线程的好处:
可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。 

多线程的不利方面:
线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 
多线程需要协调和管理,所以需要CPU时间跟踪线程; 
线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
线程太多会导致控制太复杂,最终可能造成很多Bug;

任何程序在执行时,至少有一个主线程。

 

程序工作分为默认阻塞 和主动阻塞。

主动阻塞:thread.sleep(1000) //主动阻塞1000毫秒。

如果当前只有1个线程,那么这个程序就在这里干等1秒钟。 白白浪费CPU时间。但是,通常情况我们写这样的代码的目的并不是为了让CPU去干等。等待1秒的目的是1个线程的while循环的结束,让其释放点资源给其他线程使用。

默认阻塞:当你在操作数据库的时候 //这个时候,操作未完成,数据库需要运算。如果需要1000毫秒,那么你就要等待1000毫秒。如果这个时候你的程序就只有可怜的1跟线程,那么很可怕....你的程序的效率将会很低,cpu在那干等,什么事情都没干。 这个时候你可以考虑适当增加线程,把数据库操作 和 其他操作的线程分割开来,以免数据库把你的程序默认阻塞的时候 让你白白的干等。

默认阻塞还包含以下情况:

做网络通信的时候的通信等待,I/O操作时候的操作等待,大量数据运算时候的运算等待,等等等等,这类操作通常都单启动n个线程去执行(当然,前提是满足需要的情况下尽可能减少线程),以错开系统瓶颈,让A,B,C 3件事情并行执行。而并行执行并不意味,这是应用场景,具体到应用上其实最麻烦的不是 什么时候该用,而是对公共数据操作的同步问题,这个是多线程编程比较难的地方。

而并行执行并不意味着你就多了好多资源...  并行执行只是为了不让程序白白浪费CPU时间.

说白了,只是为了让你的PC从20%CPU占用 跳到90%CPU占用。

多线程的好处之一是把许多有单独意义的事件独立处理。通过一定的优先级进行分别处理,所有的线程都是由CPU处理的,线程间通过优先级申请CPU处理。
线程应用主要在非阻塞式系统中,这个可以联想到统筹学。举个小例子理解吧:(临时想的,可能不是非常恰当,希望可以大概说明下意思)
比如CPU相当于一个人,线程要处理许多事务,比如要洗碗,烧水,煮饭,切菜等等。在烧水的时候,人可以腾出手来切菜,这时烧水和切菜就是同时进行的两个线程了,有些线程有先后顺序(同步),有些线程不能同时进行(互斥)。当然你可以选择当线程做完,就是一个时间只处理一件事情,这样CPU处理的工作量是一样的,而且轻松,但是时间就长了,效率就低了。
当然,多线程要看具体情况使用,分析需求是关键。用得好就可以节约时间了。

 

你可能感兴趣的:(java)