状态变量

Java并发多线程面试题 Top 50

吃可爱长大的小学妹 提交于 2019-12-06 14:36:22
不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者精通多线程技术并且有丰富的Java程序开发、调试、优化经验,所以线程相关的问题在面试中经常会被提到。 在典型的Java面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程, 如何创建线程,用什么方式创建线程比较好(比如: 继承thread类还是调用Runnable接口 ),然后逐渐问到并发问题像在Java并发编程的过程中遇到了什么挑战,Java内存模型,JDK1.5引入了哪些更高阶的并发工具,并发编程常用的 设计模式 ,经典多线程问题如生产者消费者,哲学家就餐,读写器或者简单的有界缓冲区问题。仅仅知道线程的基本概念是远远不够的, 你必须知道如何处理 死锁 , 竞态条件 ,内存冲突和线程安全等并发问题。掌握了这些技巧,你就可以轻松应对多线程和并发面试了。 许多Java程序员在面试前才会去看面试题,这很正常。因为收集面试题和练习很花时间,所以我从许多面试者那里收集了Java多线程和并发相关的50个热门问题。我只收集了比较新的面试题且没有提供全部答案。想必聪明的你对这些问题早就心中有数了, 如果遇到不懂的问题,你可以用Google找到答案。若你实在找不到答案,可以在文章的评论中向我求助

volatile

北战南征 提交于 2019-12-06 14:34:53
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized ”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种主要特性: 互斥(mutual exclusion) 和 可见性(visibility) 。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。 Volatile 变量 Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器

Java并发编程 (二) 并发基础

杀马特。学长 韩版系。学妹 提交于 2019-12-06 10:51:54
一、CPU多级缓存-缓存一致性 1、CPU多级缓存 ​ 上图展示的是CPU高级缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存之间有一条特殊的快速通道;在这个简化的图中,主存和缓存都连接在系统总线上,这条总线同时还用于其他组件的通信。 ​ 高速缓存出现后不久,系统变得更加复杂,高速缓存和主存之间的速度差异被拉大,直到加入L1d(又叫一级缓存)的缓存,新加入的这一个缓存比高速缓存更大,但是更慢,由于加大一级缓存的做法从经济上是行不通的。所以有了二级缓存。甚至,现在有些系统有了三级缓存。 2、CPU cache: 为什么需要CPU cache? CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题(结构: CPU -> cache - >memory ). CPU cache 有什么意义? 1)时间局部性: 如果某个数据被访问,那么在不久的将来它很可能被再次访问; 2)空间局部性: 如果某个数据被访问,那么与它相邻的数据很快也可能被访问; 3、CPU多级缓存 - 缓存一致性(MESI) 用于保证多个CPU cache之间缓存共享数据的一致 ​ M 代表modify,表示被修改;指的是该缓存行只被缓存在该CPU的缓存中,并且是被修改过的,因此

SQL中的全局变量和局部变量(@@/@)

核能气质少年 提交于 2019-12-06 08:25:41
在SQL中,我们常常使用临时表来存储临时结果,对于结果是一个集合的情况,这种方法非常实用,但当结果仅仅是一个数据或者是几个数据时,还要去建一个表,显得就比较麻烦,另外,当一个SQL语句中的某些元素经常变化时,比如选择条件,(至少我想)应该使用局部变量。当然MS SQL Server的全局变量也很有用。 >>>>局部变量 声明:DECLARE @local_variable data_type @local_variable 是变量的名称。变量名必须以 at 符 (@) 开头。data_type 是任何由系统提供的或用户定义的数据类型。变量不能是 text、ntext 或 image 数据类型。 示例: use master declare @SEL_TYPE char(2) declare @SEL_CUNT numeric(10) set @SEL_TYPE = 'U'/*user table*/ set @SEL_CUNT = 10 /*返回系统中用户表的数目*/ select @SEL_CUNT = COUNT(*) from sysobjects where type = @SEL_TYPE select @SEL_CUNT as 'User table ''s count' 如果要返回系统表的数目,可以用set @SEL_TYPE = 'S'

面试官:来!聊聊线程池的实现原理以及使用时的问题

点点圈 提交于 2019-12-05 09:54:08
扫描下方二维码或者微信搜索公众号 菜鸟飞呀飞 ,即可关注微信公众号,阅读更多 Spring源码分析 和 Java并发编程 文章。 前言   无论是在工作中,还是在书本中,我们都可以听到或者看到关于线程在使用时的一些建议:不要在代码中自己直接创建线程,而是通过线程池的方式来使用线程。使用线程池的理由大致可以总结为以下几点。 1. 降低资源消耗。线程是操作系统十分宝贵的资源,当多个人同时开发一个项目时,在互不知情的情况下,都自己在代码中创建了线程,这样就会导致线程数过多,而且线程的创建和销毁,在操作系统层面,需要由 用户态切换到内核态 ,这是一个 费时费力 的过程。而使用线程池可以避免频繁的创建线程和销毁线程,线程池中线程可以重复使用。 2. 提高响应速度。当请求到达时,由于线程池中的线程已经创建好了,使用线程池,可以省去线程创建的这段时间。 3. 提高线程的可管理性。线程是稀缺资源,当创建过多的线程时,会造成系统性能的下降,而使用线程池,可以对线程进行统一分配、调优和监控。   线程池的使用十分简单,但是会用不代表用得好。在面试中,基本不会问线程池应该怎么用,而是问线程池在使用不当时会造成哪些问题,实际上就是考察线程池的实现原理。因此搞明白线程池的实现原理是很有必要的一件事,不仅仅对面试会有帮助,也会让我们在平时工作中避过好多坑。 实现原理   在线程池中存在几个概念:核心线程数

并发知识点

有些话、适合烂在心里 提交于 2019-12-05 06:52:37
1、线程与进程 1. 进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。 2. 一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。 3. 区别不同 进程是资源分配的最小单位,线程是程序执行的最小单位。 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。 但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响

Java多线程

坚强是说给别人听的谎言 提交于 2019-12-04 11:53:55
1. 多线程 image.png 新建状态: 一个新产生的线程从新状态开始了它的生命周期。它保持这个状态直到程序 start 这个线程。 运行状态:当一个新状态的线程被 start 以后,线程就变成可运行状态,一个线程在此状态下被认为是开始执行其任务 就绪状态:当一个线程等待另外一个线程执行一个任务的时候,该线程就进入就绪状态。当另一个线程给就绪状态的线程发送信号时,该线程才重新切换到运行状态。 休眠状态: 由于一个线程的时间片用完了,该线程从运行状态进入休眠状态。当时间间隔到期或者等待的时间发生了,该状态的线程切换到运行状态。 终止状态: 一个运行状态的线程完成任务或者其他终止条件发生,该线程就切换到终止状态。 2. 僵死进程 计算机的计算模型大部分是基于空间和时间来考虑的。僵死进程唯一占用的空间是pid空间,这个空间如果不能合理的应用就会造成浪费,之所以保留这个空间,是为了让父进程感知子进程已经终止这个行为。时间方面,这个感知过程是一个异步的过程。 3. 创建线程的方式 继承 Thread 类 实现 Runnable 接口 使用 Executor 框架 法一:继承Thread类 1.1定义一个类继承Thread 1.2重写run方法 1.3创建对象 1.4调用start方法开启线程 线程对象调用run()方法和start()方法区别? 调用run方法不开启线程,仅是对象调用方法

多线程并发编程总结(一)

為{幸葍}努か 提交于 2019-12-04 01:39:51
多线程的优缺点 多线程的优点: 资源利用率更好, 程序响应更快。 多线程的代价: 设计复杂, 上下文切换开销大(先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行), 增加资源消耗(每个线程需要消耗的资源)。 线程的状态 new(新建) runnnable(可运行) running(运行) blocked(阻塞) waiting(等待) time waiting (定时等待) terminated(终止) JMM(Java内存模型) JMM定义了线程和主内存之间的抽象关系。 主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存(栈空间)中进行。 线程间的通信(传值)必须通过主内存来完成。 对于一个实例对象中的成员方法而言: 如果方法中包含本地变量是基本数据类型,将直接存储在工作内存的帧栈结构中, 但倘若本地变量是引用类型,那么该变量的引用会存储在功能内存的帧栈中,而对象实例将存储在主内存(共享数据区域,堆)中。 volatile写-读的内存语义 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。 锁释放和获取的内存语义 当线程释放锁时

这篇文章带你彻底理解synchronized

懵懂的女人 提交于 2019-12-04 00:50:32
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门 : https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 1. synchronized简介 在学习知识前,我们先来看一个现象: public class SynchronizedDemo implements Runnable { private static int count = 0; public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread thread = new Thread(new SynchronizedDemo()); thread.start(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("result: " + count); } @Override public void run() { for (int i = 0; i < 1000000; i++)

正确使用 Volatile

只谈情不闲聊 提交于 2019-12-03 22:25:14
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized ”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种主要特性: 互斥(mutual exclusion) 和 可见性(visibility) 。互斥即一次 只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些, 它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。 Volatile 变量 Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器