最近这段在看java多线程编程方面的东西。所以特写了几篇文章,来总结和回顾一下自己所学习到的相关知识。因为水平有限,文章中总结不全面甚至理解错误的地方,欢迎读者指点批评。

我们平时所接触到的程序,都是顺序编程。
顺序编程的意思是,程序中的所有事物在任意时刻都只能执行一个步骤(包括那些代码当中的顺序结构,选择结构,循环结构),
顺序编程满足了我们能够碰到的大部分问题,但是有些问题,仅仅依靠顺序编程是不够的,举个例子,一个带界面的音乐播放程序,在播放歌曲的同时也能及时的响应用户在界面上进行的的按键操作(比如点击 下一曲 按钮)。那么此时顺序编程就不合适了,因为这是需要两件同时执行的事情,如果采用顺序编程,为了及时响应按键操作,我们需要在代码的很多地方都要加上检测按键状态的代码。而这种场景下就需要并发编程了。

并发编程 有不同的实现方式。 比如 多进程模式,多线程模式等。
而最常见也最直接的就是 操作系统级别使用的进程,所谓 进程就是运行在它自己的地址空间内的自包容的程序。比如,可以在电脑上,同时并行进行几个不同的任务,qq和人聊天,酷狗播放器播放音乐,然后浏览器下着文件,这就是三个不同的进程,这三个进程彼此之间相互隔绝,不受其他进程影响。

而对于同一个进程,也可以采用多线程开发技术,使得一个程序内部多个线程可以并行运行。

当然,对于单核cpu,我们说计算机能在同一个时间点并行运行多进程或多线程。它们实际上都不是真正意义上的同一个时间点,只不过cpu切换速度极快,操作系统将cpu时间切片,分配给不同的任务。虽然看起来每个任务在执行过程中都是有时运行有时停止,但是鉴于cpu执行的速度极高,所以在我们使用者看来,那都是连续的,不间断的。这几个不同的任务就像同时并行运行一样。

而伴随着多核cpu的出现,几个核同时运行,这个时候,它们才有可能是在真正的同一个时间点并行运行。

而多线程,因为会对相同的内存空间进行并发读写操作,所以它们更加复杂。
解释一下这句话,还是 回到刚才举的那个例子,在一台电脑上,同时运行几个不同的任务。qq和人聊天,酷狗播放器播放音乐,然后浏览器下着文件。我们知道,无论什么程序,归根结底编译到了最底层,那就是0和1。因为cpu只认识0和1,如果把0和1转化为容易阅读的语言,那就是汇编语言。看过汇编的应该知道,类似 什么mov ax,bx 之类的语句都是直接操作寄存器或内存地址的。那么这个时候问题就来了,酷狗播放器,qq,浏览器这三个程序,编译到了汇编层次,那么也会直接操作寄存器和内存地址,那么为什么他们这些程序之间不冲突呢?原因就是因为 其实他们这个地址之类的,都是虚拟内存地址。酷狗播放器和qq编译成汇编语言之后,他们的内存地址都是虚拟的,所以哪怕这两个程序在汇编层面都操作同一个内存地址,也不会彼此冲突。这中间的功劳就是属于操作系统和cpu。操作系统在运行这两个进程时,会和cpu一起起作用,把他们的虚拟地址空间转换为实际的地址空间。其实说白了,就是 酷狗播放器,qq,浏览器在编写他们各自的代码的时候。根本不会考虑汇编层面上,寄存器,内存地址之类的问题。他们只需要写好自己程序本身的代码就行了。至于那些多个进程怎么运行之类的复杂问题的,上层开发的程序员们是不用关心的。

而多线程,他们归根到底还是属于同一个进程,因此多个不同线程还是对于同一内存空间进行操作,所以多线程更复杂,更容易出问题。

对于多进程,某个进程崩溃了,那么对其他进程 没啥影响,但是对于多线程,某个线程崩溃了,它所属的这个进程也会受到直接影响。

当然,我们在说不同的进程在运行的时候,都属于各自干好自己的事情,中间不会发生什么联系。这样就避免了相互干扰。不过操作系统当然也提供了进程间通信机制(IPC),比如linux的 管道,信号,套接字之类的。

而从表面上看,如果同样一个任务(进程),分解成多个线程来执行,和单独一个线程来执行,理论上前者的开销应该是更大的,原因很简单,执行多线程会增加 上下文切换的代价。但是实际上,多线程之所以更快,有两个主要因素。
(1)阻塞。程序因为程序控制之外的某些因素(比如I/0)而导致不能继续执行,cpu是如此宝贵的资源,如果cpu一直处于等待状态,那岂不是一种很大的浪费。拿i/o操作来说,cpu的执行速度极高,它的时间都是按照纳秒为单位的,但是执行程序所需要的资源或数据确往往在内存,硬盘,乃至网络服务器上,它们的速度相对于cpu那就太慢,甚至极慢。如果是顺序编程,在这种情况下,cpu只能干等着,没办法继续干活。那么这种情况下,多线程就变的很有必要了。此时cpu可以切换执行另一个任务,那么就不用干等着其中一个线程。

(2)多核cpu的出现,在最初的时候cpu都是单核的,但是到现在四核八核都很普遍的情况下,如果是顺序编程只能在某一个核上运行。找人完成一件任务,一个人单独干,和8个人协助干,虽然后者会需要花费更多的组织和协调的耗费,但是明显后者干活比前者快。

多线程编程将一个大的程序(任务/进程)划分为多个分离的,独立运行的线程(子任务),一个线程就是该进程中的 一个单一的顺序控制流,每个线程虽然没有独立的地址空间(因为只有进程才有),但是各个线程有自己的堆栈和局部变量。而在线程本身来看,就像它单独占有cpu一样。虽然底层机制是操作系统切分了cpu的时间,给它分配了这一段的时间。不过上层开发的程序员是不用关心这些的,所以这种线程模型方便了上层开发者。

-------
作者: www.yaoxiaowen.com
github: https://github.com/yaowen369

java多线程(一)-概述的更多相关文章

  1. Java多线程——<一>概述、定义任务

    一.概述 为什么使用线程?从c开始,任何一门高级语言的默认执行顺序是“按照编写的代码的顺序执行”,日常开发过程中写的业务逻辑,但凡不涉及并发的,都是让一个任务顺序执行以确保得到想要的结果.但是,当你的 ...

  2. Java 多线程 - 总结概述

    概述 菜鸟教程: Java 给多线程编程提供了内置的支持. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 多线程是多任务的一种特别的形式,但多线程 ...

  3. java多线程基本概述(一)——线程的基本认知

    1.1.概念: 进程:进程是操作系统结构的基础,是一次程序的执行:是一个程序及其数据再处理器上顺序执行时所发生的活动:是程序再一个数据集合上运行的过程,它是系统进行系统资源分配和调度的最小单元. 线程 ...

  4. java多线程基本概述(四)——死锁

    package mytask; public class Task { public static void main(String[] args) { DeadThread thread = new ...

  5. java多线程基本概述(三)——同步方法

    非线程安全其实是在多个线程对同一个对象实例的变量进行并发访问的时候发生,产生的后果就是脏读,也就是取到的数据是修改过的.而线程安全就是获得的实例变量的值是经过同步处理的,从而不会出现脏读现象. 1.1 ...

  6. java多线程基本概述(二)——Thread的一些方法

    在Thread类中有很多方法值得我们关注一下.下面选取几个进行范例: 1.1.isAlive()方法 java api 描述如下: public final boolean isAlive() Tes ...

  7. java多线程基本概述(五)——线程通信

    线程之间的通信可以通过共享内存变量的方式进行相互通信,也可以使用api提供的wait(),notify()实现线程之间的通信.wait()方法是Object类的方法,改方法用来将当前的线程置入&quo ...

  8. java多线程基本概述(七)——join()方法

    在很多情况下,主线程创建并启动子线程,如果子线程中有大量的耗时运算,主线程将早于子线程结束,如果想让主线程等待子线程结束后再结束,那么我们可以使用join()方法.调用join()方法的意思是当前线程 ...

  9. java多线程基本概述(十三)——Executor

    1:Executor接口 public interface Executor 执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等 ...

  10. java多线程基本概述(二十)——中断

    线程中断我们已经直到可以使用 interrupt() 方法,但是你必须要持有 Thread 对象,但是新的并发库中似乎在避免直接对 Thread 对象的直接操作,尽量使用 Executor 来执行所有 ...

随机推荐

  1. js 实现div模块的截图并下载功能(可制作长图)

    当需要实现html页面部分模块截图并具有保存图片功能时,前台直接生成截图并下载会方便的多.多的不说,直接看代码首先我们需要引入2个js文件: <script type="text/ja ...

  2. vue-cli 使用小技巧

    1.关闭烦人的eslint 语法检测,在 config 文件夹下 设置: // Use Eslint Loader? // If true, your code will be linted duri ...

  3. 剑指Offer_12_矩阵中的路径(参考问题:马踏棋盘)

    题目描述  请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵 ...

  4. C#将dataGridView中显示的数据导出到Excel(大数据量超有用版)

    开发中非常多情况下须要将dataGridView控件中显示的数据结果以Excel或者Word的形式导出来,本例就来实现这个功能. 因为从数据库中查找出某些数据列可能不是必需显示出来,在dataGrid ...

  5. 用R画有图例的中国地图

    近期在网上找了几种画中国地图方法,终于认为这种方法还是最适用的 1.用googlevis包.因为中国国情如今已经不能訪问google地图了.所以大多中国用户来说仅仅能望洋兴叹了. 2.用ggplot包 ...

  6. org.hibernate.LazyInitializationException could not initialize proxy-no Session的解决

    方法一:在web.xml配置延迟关闭session的过滤器 <!-- 延迟关闭session OpenSessionInViewFilter 的顺序位于struts2过滤之上 否则延迟关闭ses ...

  7. 【LDA】修正 GibbsLDA++-0.2 中的两个内存问题

    周末这两天在家用LDA做个小实验. 在LDA的众多实现的工具包中.GibbsLDA 是应用最广泛的.包含c++版本号.java版本号等.GibbsLDA++ 是它的C++版本号的实现.眼下最新版本号是 ...

  8. Esri:为Web GIS注入新内涵

    纵观近些年IT与空间技术的发展,云计算.大数据.实时信息.LBS.无人机.倾斜摄影等新技术层出不穷:互联网基础设施建设成绩瞩目,宽带成为国家战略性公共基础设施. GIS(地理信息系统)作为空间信息分析 ...

  9. ajax接收json

    l 什么是json? l Json和xml比较 l Ajax如何使用JSON l Ajax接收json响应案例 什么是json? JSON (JavaScript Object Notation) 是 ...

  10. Visual Studio 实用技能

    1快捷键使用 1. Ctrl K F 代码对齐