最近这段在看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. SQL图像查看器 —— SQL Image Viewer

    有时候往数据库里面存储了一些图片,但是如果不写读取程序的话,就不知道存储的对不对. 或者查看SQL数据库里面二进制看不懂,这个看图片很直观的. 就需要SQL Image Viewer这么一个

  2. 如何简单愉快的上手PipelineDB

    pipelineDB source:https://github.com/pipelinedb/pipelinedb 安装PipelineDB ./configure CFLAGS="-g ...

  3. pipelineDB初体验

    官网:http://www.pipelinedb.com/ pipelineDB是基于postgres的stream数据库.完全兼容pg的东西. 由于产品需要解决性能这块瓶颈,老大让试试这款基于流计算 ...

  4. linux shell中单引号、双引号和没有引号的区别

    单引号: 可以说是所见即所得:即将单引号的内的内容原样输出,或者描述为单引号里面看到的是什么就会输出什么. 双引号: 把双引号内的内容输出出来:如果内容中有命令.变量等,会先把变量.命令解析出结果,然 ...

  5. .NET Core快速入门教程 1、开篇:说说.NET Core的那些事儿

    一..NET Core的诞生 聊 .NET Core,就不得不说他的爸爸 .NET.当年Java刚刚兴起,如火如荼,微软也非常推崇Java,当时Windows平台的Java虚拟机就是微软按照JVM标准 ...

  6. 2017最新安装mysql教程及遇到的问题解决Windows下

    今天因为换了个LINUX系统 把我的E盘不小心给卸载了 结果还是不能用  导致 我E盘里面的mysql也都被删除了    所以又要在次重新装一个MYSQL 了    花了很多时间  也看了很多教程.好 ...

  7. SAP ABAP编程 Table Control动态隐藏列

    在SAP DIALOG设计中,有时候须要动态的隐藏某些列,以下是方法. ***数据定义 CONTROLS: table_control TYPE TABLEVIEW USING SCREEN 0100 ...

  8. Office Web Add-in的技术原理和开发常见问题剖析

    作者:陈希章 发表于 2017年12月20日 我过去发表过一些Office Add-in开发的文章,并且也在不同的场合分享过新的开发模式及其带来的机遇.有不少朋友给我反馈,也讨论到一些常见问题,我这里 ...

  9. Intellij IDEA更新SVN没有提示语

    更新SVN时IDE下方没有提示语句 解决方法: 点击编辑器右下方的 Event Log 按钮 打开 Show balloons 就可以显示了.

  10. C语言课程设计(成绩管理系统)

    C语言课程设计(成绩管理系统) 翻到了大学写的C语言课程设计,缅怀一下 内容: 增加学生成绩 查询学生成绩 删除 按照学生成绩进行排序 等 #include <stdio.h> #incl ...