线程和进程:

在说多线程之前,我们先来研究一下线程,说到线程,我们又不得不说到进程,因为很多初学者会把线程和进程分不清,搞混淆。

进程:

是操作系统系统运行的最小单元。怎么理解这句话,可以这样去对比,相信大家都见过积木玩具,可以搭建成很多的大型成品(操作系统Windows/Linux等等),而每一个积木都是组成这个成品的一个组件(也就是进程单元)这是操作系统和进程的关系(操作系统的组成很复杂,不是像积木简单的组合就能完成的,但是最底层原理我们可以这么想象是没有问题的)。

线程:

线程是一组指令的集合,它可以独立的运行在一个进程里。关于指令的集合:就是指我们编程里写的一个类,里面用到的关键字、方法名、变量名等等都是指令(你们可以这样去理解,完全没有问题,这里声明一下真正的指令是jvm编译成.class文件后,.class中的二进制码才是真正的指令,但是二进制码对于人类来说太多太难记,所以就用关键字来代表二进制的含义)。在这里我们又可以把线程去当成一个积木,而进程是一个个积木所组成的成品。

线程和进程的区别:

通过上面的例子,不难理解进程和线程之间的关系,进程包含线程,线程是进程的一个单元。所以在这里我们要注意一下,在进程中至少包含一个线程(主线程)。(这样讲,一个积木都没有还会有成品吗)

总结:进程是所有线程的集合,每一个线程是进程中的一条执行路径。

详解多线程:

在上面的例子中,我们知道线程和进程的区别,对于多线程的具体作用我们在这里详细解释。

并发

并发:多个线程在一个单核cpu上进行资源抢占并运行,就是并发。
多线程在cpu中是并发运行的(下面会详细解释并发,还有和并行的区别)
首先我们要知道在cpu(这里指的是单核cpu)中在某一个时间片,只能有一个线程在cpu中运行。一个cpu在同一时间只能执行一个线程。

为什么使用并发

在一个进程中有多个线程需要执行,这些线程会抢占cpu的时间片来运行自身。有人会问,为什么不等一个线程执行完之后再去执行另一个线程呢?思考一下,我们在使用电脑的时候,可以同时看文档,听音乐。如果cpu设计成一个线程执行完之后再去执行另一个线程,你就只能听完音乐,在去看文档,在听音乐的过程中你的鼠标都移动不了(鼠标也是一个单独线程),你们觉得这样的体验好吗,所以cpu肯定不能这样设计。

并发的执行原理

操作系统是以抢占式的方法来调度线程的(也有其他方法,我们目前先学这一种)。就是线程自己去强cpu的资源,谁先抢到谁就在cpu上运行一个时间片(这个时间片很短很短)。这里的线程会有优先级的特点,优先级高的线程抢到cpu的概率大,概率大,概率大(是概率大,不代表一定能抢到)运行完成之后释放cpu资源,回去重新抢占cpu。因为运行的时间很短,所以在人为感官上觉得这些线程始再同时运行的。
其实上面多个线程抢占cpu资源就是多线程的并发。

注意:这里是一个cpu。随着需求的不断增高,科技的不断发展,单核cpu的性能已经不能满足效率。于是就出现了多核cpu,也就出现了并行

并行

并行:在同一时间点,多个线程同时运行在多核cpu的多个核上,这叫并行。和并发不同的是:同一时间,在并行中,线程可以同时运行,而并发则只能有一个线程运行。

线程的五种状态:

创建状态:

当用new操作符创建一个线程时, 例如new Thread®,线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

就绪状态:

一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。
处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

运行状态:

当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

阻塞状态:

线程运行过程中,可能由于各种原因进入阻塞状态:
1>线程通过调用sleep方法进入睡眠状态;
2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
3>线程试图得到一个锁,而该锁正被其他线程持有;
4>线程在等待某个触发条件;

死亡状态:

有两个原因会导致线程死亡:
1> run方法正常退出而自然死亡,
2> 一个未捕获的异常终止了run方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

如图所示:

线程的创建方式:

继承Thread

实现Runnable

匿名内部类方式


上面只要会继承THread类方法和实现Runnable接口这两种就行,还有其他的线程池创建等等,在后面的章节说

迷惑问题

继承THread类方法和实现Runnable接口 这两种方式选择哪一种好呢?

在java语言中,有一个特点,就是单继承,多实现。实现了接口还可以继续继承,继承了类不能再继承。所以一般情况下使用实现Runnable会有更好的拓展性。

继器启动线程是调用run方法还是start方法

Run方法仅仅只是线程所要执行的代码块部分,如果调用run方法,就和调用其他普通方法一样,从上到下,顺序执行。没有了多线程的特点。所以使用start方法使线程进入就绪状态。

线程的分类:

用户线程(也叫前台线程):

用户自定义创建的线程,用户线程的状态不受其他线程的影响。别的线程挂了就挂了,影响不到他,因为他们是互相独立的。

守护线程(也叫后台线程):

守护线程受用户线程的影响,当用户线程销毁后,守护线程也会跟着销毁。比如GC

一定要看的干货

白话说编程之java线程的更多相关文章

  1. QT核心编程之Qt线程 (c)

    QT核心编程之Qt线程是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容. Qt对线程提供了支持,它引入了一些基本与平台无关的线程类 ...

  2. 三、VIP课程:并发编程专题->01-并发编程之Executor线程池详解

    01-并发编程之Executor线程池详解 线程:什么是线程&多线程 线程:线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系 ...

  3. python并发编程之Queue线程、进程、协程通信(五)

    单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ...

  4. python并发编程之threading线程(一)

    进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源. 系列文章 py ...

  5. [转]c++多线程编程之pthread线程深入理解

    多线程编程之pthread线程深入理解         Pthread是 POSIX threads 的简称,是POSIX的线程标准.           前几篇博客已经能给你初步的多线程概念.在进一 ...

  6. 多线程之Java线程阻塞与唤醒

    线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题.如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节.在Java ...

  7. 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则

    前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...

  8. 并发编程之 Java 三把锁

    前言 今天我们继续学习并发.在之前我们学习了 JMM 的知识,知道了在并发编程中,为了保证线程的安全性,需要保证线程的原子性,可见性,有序性.其中,synchronized 高频出现,因为他既保证了原 ...

  9. 并发编程之Java内存模型

    在介绍Java内存模型之前,先来了解一下为什么要有内存模型,以及内存模型是什么.然后我们基于对内存模型的了解,学习Java内存模型以及并发编程的三大特性. 为什么要有内存模型 在计算机中,所有的运算操 ...

随机推荐

  1. vue2.0:项目开始,首页入门(main.js,App.vue,importfrom)

    对main.js App.vue 等进行操作: 但是这就出现了一个问题:什么是main.js,他主要干什么用的?App.vue又是干什么用的?main.js 里面的import from又在干嘛?ne ...

  2. SpringBoot入门系列(七)Spring Boot整合Redis缓存

    前面介绍了Spring Boot 中的整合Mybatis并实现增删改查,.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/ ...

  3. vs2017打包exe安装包

    1,安装扩展程序Install Projects 2,在打开的界面搜索Install,找到Install Projects 3,在要打包的项目解决方案下创建一个生成exe的项目 4,在打包项目的文件系 ...

  4. 阅读GitHub源码的正确打开方式

    前言 近来发现阅读开源项目上手就整最新的代码不合适,缺少项目迭代的具体实现过程,想着若是可以看到针对问题的提交代码就好了,所以就有了本篇博客. 以文主要涉及:如何fork开源项目,如何保证本地仓库代码 ...

  5. 【Weiss】【第03章】练习3.2

    [练习3.2] 给你一个链表L和另一个链表P,它们包含以升序排列的整数.操作printlots(L,P)将打印L中那些由P所指定的位置上的元素. 例如,如果p=1,3,4,6,那么,L的第一.第三.第 ...

  6. Natas20 Writeup(Session登录,注入参数)

    Natas20: 读取源码,发现把sessionID存到了文件中,按键值对存在,以空格分隔,如果$_SESSION["admin"]==1,则成功登陆,得到flag.并且通过查询所 ...

  7. Spring MVC系列-(3) Bean的装配

    3. 高级装配Bean 3.1 Bean的作用域 默认情况下,Spring中的bean都是以单例的形式存在的,无论注入多少次,每次注入的都是同一个实例. 考虑到某些bean可能是可变的,Spring定 ...

  8. python3正则提取字符串里的中文

    # -*- coding: utf-8 -*- import re #过滤掉除了中文以外的字符 str = "hello,world!!%[545]你好234世界..." str ...

  9. [ICRA 2019]Multi-Task Template Matching for Object Detection, Segmentation and Pose Estimation Using Depth Images

    简介         本文作者提出新的框架(MTTM),使用模板匹配来完成多个任务,从深度图的模板上找到目标物体,通过比较模板特征图与场景特征图来预测分割mask和模板与检测物体之间的位姿变换.作者提 ...

  10. elasticsearch和kibana安装后,外网无法访问

    问题描述: 现在解压elasticsearch之后,启动,通过http://localhost:9200可以访问的到,但是http://ip:9200访问不到 解决方法: 修改elasticsearc ...