线程安全

2020年JAVA大厂笔经面经

帅比萌擦擦* 提交于 2020-02-28 21:20:41
个人简介 ​ Java后台开发方向。 非计算机专业硕士,专业涉及到一些开发。 实验室项目主要是Java Web系统,挖掘小亮点。 无实习经验。 闲话唠嗑 ​ 回顾这几个月,宛若梦一场。 一开始心态不好,看到要学习的东西一大堆,沉不下心来学习,看什么东西都是看着看着就很浮躁,开始疯狂抖腿,沉迷幻想,以为找工作只看少量面经重点即可。 实验室原因无法实习,四五月份春招的时候参加了阿里和网易的实习招聘提前感受面试,惨败。可以说是一塌糊涂。当头一棒,脑子清醒了,既然想要从事互联网行业,早学晚学还是要学,不如现在踏踏实实好好学,一生受用(室友的面试官对她说的原话,感觉很有道理)。开始分阶段制定学习计划,每碰到一个知识点就来牛客查相关面经问题,逐个攻破。 总共投了三十多家公司,大小公司都有,想给自己多几个机会,到提前批结束为止只有十家左右有回复。目前收到阿里盒马、腾讯在线教育、网易严选、头条抖音、华为Cloud BU这几个意向offer。 易紧张体质,一紧张就肠道蠕动汗如雨下,题目答得歪七歪八了,编程题也做不出来了,但面试面多一些紧张感就好一些,不考虑结果,只思考问题,就会好很多了。 能够拿到offer得益于牛客上大家的面经分享和在线编程练习,是时候回报牛客啦,当然是恭喜各位收到offer的小伙伴们,但是暂时没收到offer的小伙伴们也不用着急,沉下心来好好学习,offer总会有的。

单例模式

痴心易碎 提交于 2020-02-28 19:51:24
这篇文章中我会用8种写法来对单例模式进行优化,以达到最完美的效果 但是说实话在平常我们进行代码编写的时候用不着那么完美 单例模式 什么是单例模式? 简单的说就是只能new出来一个实例 第一种写法 饿汉式:   优点:简单实用   缺点:不论该对象是否会被用到,都提前将对象实例化 1.首先我们创建出一个静态的不可更改的变量Instance 2.我们将该类的构造方法的权限设置为private,防止其他类new对象 3.设置该对象的get方法 1 /** 2 * 饿汉式 3 * 类加载到内存后,就实例化一个单例,JVM保证线程安全 4 * (JVM保证每一个class只会露到内存一次,那么static变量在class露到内存之后马上进行初始化,所以static变量也保证初始化这一次) 5 * 简单实用,推荐使用 6 * 唯一缺点:不管用到与否,类加载时就完成实例化 7 */ 8 public class Mgr01 { 9 private static final Mgr01 Instance = new Mgr01(); 10 11 private Mgr01(){} 12 13 public static Mgr01 getInstance(){return Instance;} 14 15 public static void main(String[] args) { 16 /*

5.6 Vector向量

爱⌒轻易说出口 提交于 2020-02-28 12:47:50
Vector基础知识 底层实现 如何选择 底层实现 Vector底层是用数组实现的List,相关的方法都加了同步检查,因此线程安全,效率低。Vector使用方法参照ArrayList以及LinkedList。 如何选择 需要线程安全时,用Vector; 不存在线程安全问题时,并且查找较多,用ArrayList; 不存在线程安全问题时,增加或删除元素较多用LinkedList。 来源: CSDN 作者: dxt_snow 链接: https://blog.csdn.net/qq_37665301/article/details/104553264

java HashMap、HashTable、ConcurrentHashMap区别

一笑奈何 提交于 2020-02-28 12:22:39
HashTable 底层数组+链表实现,无论key还是value都 不能为null ,线程 安全 ,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化 初始size为 11 ,扩容:newsize = olesize*2+1 计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length Hashtable的enumerator迭代器不是fail-fast HashMap 底层数组+链表实现,可 以存储null键和null值 ,线程 不安全 初始size为 16 ,扩容:newsize = oldsize*2,size一定为2的n次幂 扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入 当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀 HashMap的迭代器(Iterator)是fail-fast迭代器 在HashMap中,null可以作为键,这样的键只有一个,但可以有一个或多个键所对应的值为null。 当get()方法返回null值时,即可以表示HashMap中没有该key,也可以表示该key所对应的value为null 。因此,在HashMap中不能由get(

多线程——创建线程、线程安全问题

馋奶兔 提交于 2020-02-28 07:22:41
文章目录 程序、进程、线程 创建线程 启动线程 线程安全 解决线程安全问题(实现Runnable)——同步代码块 解决线程安全问题(实现Runnable)——同步方法 解决线程安全问题(继承Thread)——同步代码块 解决线程安全问题(继承Thread)——同步方法 解决线程安全问题方式三:Lock锁 --- JDK5.0新增 Synchronized与Lock的异同 程序、进程、线程 程序:是为完成特定任务、用某种语言编写的一组指令的集合。即一段静态的代码,静态对象。 进程:是程序产生的一次执行过程,或是正在运行的一个程序。是一个动态的过程:由它自身 的产生、存在和消亡的过程——生命周期。 > 如:运行中的QQ,运行中的MP3播放器 > 程序是静态的,进程是动态的 > 进程作为资源分配的单位,系统在运行时会为每个进程分匹配不同的内存区域 线程:进程可进一步细化为线程,是一个程序内部的一条执行的路径。 > 若一个进程同时并行执行多个线程,就是支持多线程的 > 线程作为进程调度和执行的最小单位,每个线程拥有独立的运行栈和程序计数器 ( pc ) ,线程切换的开销小 > 一个进程中的多个线程共享相同的内存单元/内存地址空间- > 他们从同一堆中分配对象,可以访问呢相同的 变量和对象。这就使得线程间通信更便捷、高效、。但是多个线程操作共享的系统资源可能会带来安全的隐患。 创建线程 1

Java中String、StringBuffer、StringBuilder的区别

拈花ヽ惹草 提交于 2020-02-28 05:33:58
关于这三者的应用场景: String:适用于少量的字符串操作的情况; StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况; StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况; 这三者场景不同,是由其多方面原因造成的。 1.运行的速度快慢:StringBuilder > StringBuffer > String 1.1 String最慢的原因:String为字符串常量,使用常量类型的字符数组保存值,其对象一旦创建,将不可更改。 String a="hello"; a=a+" world"; 这样的操作,貌似a变量被改变了,实际这只是一种假象,JVM对于这几行代码是这样处理的:首先创建一个String对象a,并把“hello”赋值给a,然后JVM又创建了一个新的对象也名为a,把原来的a的值和“ world”加起来再赋值给新的a,而原来的a就会被JVM的垃圾回收机制(GC)给回收掉了,所以,a并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,执行速度很慢。 1.2 而StringBuffer和StringBuilder都继承自AbstractStringBuilder类

String 和 StringBuffer、StringBuilder 的区别是什么?String 为什 么是不可变的?

懵懂的女人 提交于 2020-02-28 03:48:59
可变性 简单的来说:String 类中使用 final 关键字字符数组保存字符串, private final char value[] ,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串 char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。 StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。 线程安全性 String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共 方法。 StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。 StringBuilder 并没有对 方法进行加同步锁,所以是非线程安全的。 性能 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String

Java并发高频面试题

雨燕双飞 提交于 2020-02-27 21:24:15
前面整理了Java基础、Mysql、Spring的高频面试题,今天为大家带来Java并发方面的高频面试题,因为并发知识不管在学习、面试还是工作过程中都非常非常重要,看完本文,相信绝对能助你一臂之力。 1、线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程。每个进程都有自己的内存空间,可执行代码和唯一进程标识符(PID)。 每条线程并行执行不同的任务。不同的进程使用不同的内存空间(线程自己的堆栈),而所有的线程共享一片相同的内存空间(进程主内存)。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。 2、实现多线程的方式有哪些? 继承Thread类:Java单继承,不推荐; 实现Runnable接口:Thread类也是继承Runnable接口,推荐; 实现Callable接口:实现Callable接口,配合FutureTask使用,有返回值; 使用线程池:复用,节约资源; 更多方式可以参考我的文章使用Java Executor框架实现多线程 3、用Runnable还是Thread? 这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程,问题是,那个方法更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类

AtomicReference与volatile的区别

穿精又带淫゛_ 提交于 2020-02-27 08:53:29
首先volatile是java中关键字用于修饰变量,AtomicReference是并发包java.util.concurrent.atomic下的类。 首先volatile作用,当一个变量被定义为volatile之后,看做“程度较轻的 synchronized”,具备两个特性: 1.保证此变量对所有线程的可见性(当一条线程修改这个变量值时,新值其他线程立即得知) 2.禁止指令重新排序 注意volatile修饰变量不能保证在并发条件下是线程安全的,因为java里面的运算并非原子操作。 volatile说明 java.util.concurrent.atomic工具包,支持在单个变量上解除锁的线程安全编程。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。 AtomicReference说明 Java 理论与实践: 正确使用 Volatile 变量 Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized ”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少

Java多线程整理

空扰寡人 提交于 2020-02-27 08:50:24
目录: 1.volatile变量 2.Java并发编程学习 3. CountDownLatch用法 4. CyclicBarrier使用 5.BlockingQueue使用 6.任务执行器Executor 7.CompletionService使用 8.ConcurrentHashMap使用 9.Lock使用 一、 volatile变量   1.volatile原理:volatile的原理实际上是告诉处理器,不要把变量缓存在寄存器或者相对于其他处理器不可见的地方,而是把变量放在主存,每次读写操作都在主存上进行操作。另外,被申明为volatile的变量也不会与其它内存中的变量进行重排序。   2.volatile同步:volatile是同步的一个子集,只保证了变量的可见性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。相对于同步而言,volatile的优势:a.简易性,可以像使用其他变量一样使用volatile变量;b.volatile变量不会造成线程阻塞;c.如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。   3.正确使用volatile条件:对变量的写操作不依赖于当前值;该变量没有包含在具有其他变量的不变式中; /* * 对于第一条原则:对变量的写操作不依赖于当前值; * 虽然i++只有一条语句