JAVA并发知识

JAVA并发知识

    • 一、什么是线程和进程?
    • 二、线程与进程的关系,区别及优缺点?
    • 三、并发和并行有什么区别?
    • 四、为什么要使用多线程?
    • 五、使用多线程可能会带来什么问题?
    • 六、说说线程的生命周期和状态。
    • 七、java 中如何创建线程?
    • 八、什么是上下文切换?
    • 九、什么是线程死锁?怎么避免?
      • 死锁:
      • 为什么会出现死锁?
      • 死锁产生的四个条件:
      • 怎么避免线程死锁?
    • 十、sleep() 方法和 wait() 方法区别和共同点
    • 十一、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?

一、什么是线程和进程?

进程:
是程序的一次执行过程,是系统运行程序的基本单元(就比如打开某个应用,就是开启了一个进程),因此进程是动态的。系统运行一个程序即是一个程序从创建、运行到消亡的过程。

在 Java 中,当我们启动 main 函数时其实就是启动了 JVM 进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。

线程:
线程与就进程相似,但线程是一个比进程更小的执行单位。一个进程在执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

二、线程与进程的关系,区别及优缺点?

一个进程可以有多个线程,多个线程共享进程的堆和方法区(JDK 1.8 之后的元空间)资源。但是每个线程有自己的程序计数器、虚拟机栈和本地方法栈。

综上:线程是进程划分成的更小的运行单位。线程与进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程则相反。

为什么程序计数器、虚拟机栈和本地方法栈是线程私有的呢?为什么堆和方法区是线程共享的呢?

(1) 程序计数器为什么是私有的?

首先明确程序计数器的作用:

  • 字节码解释器通过改变程序计数器来一次读取指令,从而实现代码的流程控制。如:顺序执行、选择、循环、异常处理。
  • 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程运行到哪了。

需要注意的是:如果执行的是 native 方法,那么程序计数器记录的是 undefined 地址,只有执行的是 Java 代码时程序计数器记录的才是下一条指令的地址。

所以,程序计数器私有主要是为了线程切换后能够恢复到正确的执行位置。

(2) 虚拟机栈和本地方法栈为什么是私有的?

  • 虚拟机栈:每个Java 方法在执行的同时会创建一个帧栈用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至完成的过程,就对应一个帧栈在 Java 虚拟机中入栈和出栈的过程。
  • 本地方法栈:和虚拟机的作用非常相似。区别是:虚拟机为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 native 方法服务。在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。

所以,为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地方法栈是线程私有的。

(3) 堆和方法区

堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用来存放新创建的对象(所有的对象都在这里分配内存);方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。

三、并发和并行有什么区别?

  • 并发:同一时间段,多个任务都在执行(单位时间内不一定同时执行);
  • 并行:单位时间内,多个任务同时执行。

并发的关键是你有处理多个任务的能力,不一定要同时。 而并行的关键是你有同时处理多个任务的能力。

四、为什么要使用多线程?

先总体上:

  • 从计算机底层来说:线程可以比作是轻量级的进程,是程序执行的最小单元,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
  • 从当代互联网发展趋势来说:现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正式开发高并发系统的基础,利用好多线程机制可以大大提高系统的并发能力以及性能。

再深入到计算机底层:

  • 单核时代:在单核时代多线程主要是为了提高 CPU 和 IO 设备的综合利用率。
  • 多核时代:多核时代主要是为了提高 CPU 的利用率。

五、使用多线程可能会带来什么问题?

并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、死锁等,还有受限于硬件和软件和资源闲置问题。

六、说说线程的生命周期和状态。

Java 线程在运行的生命周期中的指定时刻只可能指定处于下面几种不同状态的其中一个状态:

  1. 新建状态(NEW):新创建了一个线程对象;
  2. 就绪状态(RUNNABLE):线程创建后,其他线程调用了该对象的 start() 方法。该方法状态的线程位于可运行线程池中,变得可运行,等待获取 CPU 的使用权;
  3. 运行状态(RUNNING):就绪状态的线程获取了 CPU,执行程序代码;
  4. 阻塞状态(BLOCKED):阻塞状态是线程因为某种原因放弃 CPU 使用权,暂时停止运行。知道线程进入就绪状态,才有机会转到运行状态。阻塞的情况分为三种:
    • 等待阻塞:运行的线程执行 wait() 方法,JVM 会把该线程放入线程池中。
    • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池中。
    • 其他阻塞:运行的线程执行 sleep() 或 join() 方法,或者发出了 I/O 请求时,JVM 会把该线程设置为阻塞状态。当 sleep() 超时、join() 等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入就绪状态。
  5. 死亡状态(DEAD):线程执行完了或者因异常退出了 run() 方法,该线程结束生命周期。

线程在生命周期中并不是固定处于一个状态,而是随着代码的执行在不同状态之间切换。

七、java 中如何创建线程?

Java 中创建线程有四种方式:① 继承 Thread;② 实现 Runnable 接口;③ 线程池;④ 实现 Callable 接口。

关于 Thread 或者 Runnable 接口,首先 Runnable 是接口,实现了改接口的类还可以继承其他类,更灵活;其次,Runnable 任务可以在 Executors 中或者 ExecutorService 提交运行。

Future 和 Callable:Callable 与 Runnable 一样都是代表抽象的计算任务,其中的 call 方法做用与 run 一样,但是会返回一个值。Future 表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果。ExecutorService 中所有的 submit 方法都会返回一个 future。

Callable 和 Runnable 的区别:

  • Callable 定义的方法是 call,而 Runnable 定义的方法是 run;
  • Callable 的 call 方法可以有返回值,而 Runnable 的 run 方法不能有返回值;
  • Callable 的 call 方法可以抛出异常,而 Runnable 的 run 方法不能抛出异常。

八、什么是上下文切换?

多线程编程中一般线程的个数都大于 CPU 核的个数,而一个 CPU 核在任意时刻只能被一个线程使用,为了让这些县城都能得到有效执行,CPU 采取的策略是为每个线程分配时间片并轮转的形式。当一个线程是时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。也就是:当任务执行完, CPU 时间片切换到另一个任务之前会先保存自己的状态,以便于再切换回这个任务时,可以加载这个任务的状态。任务从保持到再加载的过程就是一个上下文切换。

上下文切换通常是计算密集型的。也就是说,它需要相当可观的处理器时间,在每秒几十上百次的切换中,每次切换都需要纳秒量级的时间。所以,上下文切换对系统来说意味着消耗大量的 CPU 时间,事实上,可能是操作系统中时间消耗最大的操作。

Linux 相比与其他操作系统(包括其他类 Unix 系统)有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。

九、什么是线程死锁?怎么避免?

死锁:

两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待的现象。

为什么会出现死锁?

Java 运行多线程并发控制,当多个线程同时操作一个共享的资源变量时(如数据的增删改查),将会导致数据出现不正确的结果,相互之间产生冲突,因此加入锁保证了该变量的唯一性和准确性。

死锁产生的四个条件:

  1. 互斥条件: 该资源任意一个时刻只由一个线程占用;
  2. 请求与保持条件:一个线程因请求资源而阻塞,对已获得的资源保持不放;
  3. 不剥夺条件:线程已经获得的资源在未使用完之前不能被其他线程强行剥夺,只由自己使用完毕后才释放资源;
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

怎么避免线程死锁?

只需要破坏产生死锁的四个条件之一即可。

  • 破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本身就是想让他们互斥的(临界资源需要互斥访问)。
  • 破坏请求与保持条件:一次性申请所有的资源
  • 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
  • 破坏循环等待条件:靠按顺序申请资源来预防。按照某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

十、sleep() 方法和 wait() 方法区别和共同点

  • 两者最主要的区别在于:sleep() 方法没有释放锁,而 wait() 方法释放了锁;
  • 两者都可以暂停多线程;
  • wait() 通常被用于线程间交互/通信,sleep() 通常被用于暂停执行;
  • wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep 执行完后,会自动苏醒。

十一、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?

new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入就绪状态,当分配到时间片后就可以开始运行了。start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。而直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这不是多线程工作。

总之:调用 start() 方法可启动线程并使线程进入就绪状态,而 run() 方法只是 thread 的一个普通方法,还是在主线程里执行的。

原文参考:https://www.cnblogs.com/reformdai/p/11039843.html

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

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

相关文章

servlet session持久化

1、 session持久化是什么? web服务器把 session中存储的属性存储到本地磁盘或数据库中; 2、为什么需要持久化? 因为 session是服务器维护会话状态的对象,即便客户端关闭连接或客户端长时间没有访问,服务器还依然存储…

高并发解决方案

扩容 垂直扩容:提高系统部件能力水平扩容:增加更多系统成员(增加服务器数量) 数据库扩容系统属于 读操作 频繁型,可采用垂直扩容 采用 memcache, redis, CDN等缓存系统属于 写操作 频繁型&#…

servlet session 跟踪用户上次访问时间

1、是什么? 上次访问时间;即用户最近一次登录时间; 2、为什么? 为了提示用户登录或访问记录,提高安全性,如qq登录提示; 3、怎么做? 通过cookie 实现; 用户第1次登录&…

Spring MVC表单防重复提交

转载自 Spring MVC表单防重复提交 利用Spring MVC的过滤器及token传递验证来实现表单防重复提交。 创建注解 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface Token {boolean create() default false;boolean remove() default f…

SpringMvc @RequestParam、 @RequestBody、@RequestPart 的区别

注解RequestParam接收的参数是来自requestHeader中,即请求头。 RequestParam可以接受简单类型的属性,也可以接受对象类型。 RequestParam有三个配置参数: required 表示是否必须,默认为 true,必须。defaultValue 可…

利用session防止表单重复提交

1、是什么?一个表单不能多次提交; 2、为什么? 在网络不好或者并发请求时会导致多次重复提交数据的问题。防止重复提交,可以维护数据一致性; 3、怎么做? 把 session的编号和当前时间戳经过 MD5 加密得到to…

Druid-目前最好的连接池

转载自 Druid-目前最好的连接池 Druid是什么 Druid是阿里开源的连接池,是Java语言中最好的数据库连接池.Druid能够提供强大的监控和扩展功能,是为监控而生的数据库连接池! GitHub:https://github.com/alibaba/druid/ 添加依赖 &l…

Nginx 部署 Vue 项目刷新页面出现404

问题 使用Vue.框架,利用vue-route编写了一个单页路由项目,运维协助在服务器端配置nginx。部署完成后,访问首页没问题,从首页里打开二级页面没问题,但是所有的二级页面打开后,再次刷新,就会出现…

repost: intro2token

repost 4 https://blog.csdn.net/Jason_Fangh/article/details/55113627 对于初学者来说,对Token和Session的使用难免会限于困境,开发过程中知道有这个东西,但却不知道为什么要用他?更不知道其原理,今天我就带大家一…

vue - resource 使用过程的坑

一. get 传参的坑:加params对象传参(不能直接get(url, params)!!!) this.$http.get(url, {params: { offset: this.offset, label: this.categray }})二. 使用post请求: 知识点 post参数的形式 form data(表单,通过url…

repo-关于URL编码

repost 4 http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 一、问题的由来 URL就是网址,只要上网,就一定会用到。 一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。比如&#xff0c…

Spring零配置之@Configuration注解详解

转载自 Spring零配置之Configuration注解详解 Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而Spring3.0之后可以不要配置文件了,通过注解Configuration完全搞定。 Configuration即用来代替S…

session实现购物车

1、是什么? session 可以存储会话级变量,基于其实现购物车; 2、为什么? session是会话级变量,可以吧多次请求的数据串联起来,放到会话里; 3、怎么做? 【荔枝】转自 张孝祥 登录…

commons-logging,log4j,logback,slf4j之间的关系详解

转载自 commons-logging,log4j,logback,slf4j之间的关系详解commons-logging是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面,使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者…

Vue代理配置

在 package.json 的同级目录(项目根目录)下创建 vue.config.js在 vue.config.js 写入下列内容 module.exports {devServer: {proxy: http://localhost:8080}}这会告诉开发服务器将任何未知请求 (没有匹配到静态文件的请求) 代理到 http://localhost:40…

@Resource,@Autowired,@Inject3种注入方式详解

转载自 Resource,Autowired,Inject3种注入方式详解 概况 Resource,Autowired,Inject 这3种都是用来注入bean的,它们属于不同的程序中。 ANNOTATIONPACKAGESOURCEResourcejavax.annotationJava JSR-250Injectjavax.injectJava JSR-330Autowiredorg.springframework.b…

repost-微信小程序入门教程之一:初次上手

repost 4 http://www.ruanyifeng.com/blog/2020/10/wechat-miniprogram-tutorial-part-one.html 微信是中国使用量最大的手机 App 之一,日活跃用户超过3亿,月活跃用户超过11亿(2019年底统计),市场极大。 2017年&#x…

Spring MVC : 概念模型 HandlerMethod(转载)

Spring MVC 应用启动时会搜集并分析每个 Web 控制器方法&#xff0c;从中提取对应的"<请求匹配条件,控制器方法>“映射关系&#xff0c;形成一个映射关系表保存在一个 RequestMappingHandlerMapping bean 中。然后在客户请求到达时&#xff0c;再使用 RequestMappin…

repo-话说软件详细设计工具

repost 4 https://blog.csdn.net/tang_huan_11/article/details/8043481 在软件设计是需要写软件详细说明书,设计此文档的时候,肯定少不了工具.现在我们就来了解一下软件详细设计的 工具. 1)程序流程图 程序流程图又称为程序框图,它是最古老,应用最广泛且最有争议描述详细设计的…

你必须了解Spring的生态

转载自 你必须了解Spring的生态 Spring不止是提供了IOC、AOP的功能&#xff0c;还提供了大量的基于Spring的项目&#xff0c;拿来用就行了&#xff0c;用于一站式开发&#xff0c;大大降低了开发的难度。 下面列举下主要的一些Spring的生态项目&#xff1a; Spring Boot&#…