首页 文章 精选 留言 我的

精选列表

搜索[禅道],共6193篇文章
优秀的个人博客,低调大师

这9道面试题,给你答案都不一定能看明白,但面试必问,建议看完

1. synchronized的实现原理以及锁优化? synchronized的实现原理 synchronized作用于「方法」或者「代码块」,保证被修饰的代码在同一时间只能被一个线程访问。 synchronized修饰代码块时,JVM采用「monitorenter、monitorexit」两个指令来实现同步 synchronized修饰同步方法时,JVM采用「ACC_SYNCHRONIZED」标记符来实现同步 monitorenter、monitorexit或者ACC_SYNCHRONIZED都是「基于Monitor实现」的 实例对象里有对象头,对象头里面有Mark Word,Mark Word指针指向了「monitor」 Monitor其实是一种「同步工具」,也可以说是一种「同步机制」。 在Java虚拟机(HotSpot)中,Monitor是由「ObjectMonitor实现」的。ObjectMonitor体现出Monitor的工作原理~ ObjectMonitor() { _header = NULL; _count = 0; // 记录线程获取锁的次数 _waiters = 0, _recursions = 0; //锁的重入次数 _object = NULL; _owner = NULL; // 指向持有ObjectMonitor对象的线程 _WaitSet = NULL; // 处于wait状态的线程,会被加入到_WaitSet _WaitSetLock = 0 ; _Responsible = NULL ; _succ = NULL ; _cxq = NULL ; FreeNext = NULL ; _EntryList = NULL ; // 处于等待锁block状态的线程,会被加入到该列表 _SpinFreq = 0 ; _SpinClock = 0 ; OwnerIsThread = 0 ; } 复制代码 ObjectMonitor的几个关键属性 count、recursions、owner、WaitSet、 _EntryList 体现了monitor的工作原理 锁优化 在讨论锁优化前,先看看JAVA对象头(32位JVM)中Mark Word的结构图吧~ Mark Word存储对象自身的运行数据,如「哈希码、GC分代年龄、锁状态标志、偏向时间戳(Epoch)」 等,为什么区分「偏向锁、轻量级锁、重量级锁」等几种锁状态呢? ❝ 在JDK1.6之前,synchronized的实现直接调用ObjectMonitor的enter和exit,这种锁被称之为「重量级锁」。从JDK6开始,HotSpot虚拟机开发团队对Java中的锁进行优化,如增加了适应性自旋、锁消除、锁粗化、轻量级锁和偏向锁等优化策略。 ❞ 偏向锁:在无竞争的情况下,把整个同步都消除掉,CAS操作都不做。 轻量级锁:在没有多线程竞争时,相对重量级锁,减少操作系统互斥量带来的性能消耗。但是,如果存在锁竞争,除了互斥量本身开销,还额外有CAS操作的开销。 自旋锁:减少不必要的CPU上下文切换。在轻量级锁升级为重量级锁时,就使用了自旋加锁的方式 锁粗化:将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁。 ❝ 举个例子,买门票进动物园。老师带一群小朋友去参观,验票员如果知道他们是个集体,就可以把他们看成一个整体(锁租化),一次性验票过,而不需要一个个找他们验票。 ❞ 锁消除:虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。 有兴趣的朋友们可以看看我这篇文章: Synchronized解析——如果你愿意一层一层剥开我的心[1] 2. ThreadLocal原理,使用注意点,应用场景有哪些? 回答四个主要点: ThreadLocal是什么? ThreadLocal原理 ThreadLocal使用注意点 ThreadLocal的应用场景 ThreadLocal是什么? ThreadLocal,即线程本地变量。如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程安全问题。 //创建一个ThreadLocal变量 static ThreadLocal<String> localVariable = new ThreadLocal<>(); 复制代码 ThreadLocal原理 ThreadLocal内存结构图: 由结构图是可以看出: Thread对象中持有一个ThreadLocal.ThreadLocalMap的成员变量。 ThreadLocalMap内部维护了Entry数组,每个Entry代表一个完整的对象,key是ThreadLocal本身,value是ThreadLocal的泛型值。 对照这几段关键源码来看,更容易理解一点哈~ public class Thread implements Runnable { //ThreadLocal.ThreadLocalMap是Thread的属性 ThreadLocal.ThreadLocalMap threadLocals = null; } 复制代码 ThreadLocal中的关键方法set()和get() public void set(T value) { Thread t = Thread.currentThread(); //获取当前线程t ThreadLocalMap map = getMap(t); //根据当前线程获取到ThreadLocalMap if (map != null) map.set(this, value); //K,V设置到ThreadLocalMap中 else createMap(t, value); //创建一个新的ThreadLocalMap } ​ public T get() { Thread t = Thread.currentThread();//获取当前线程t ThreadLocalMap map = getMap(t);//根据当前线程获取到ThreadLocalMap if (map != null) { //由this(即ThreadLoca对象)得到对应的Value,即ThreadLocal的泛型值 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } 复制代码 ThreadLocalMap的Entry数组 static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; ​ Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } } 复制代码 所以怎么回答「ThreadLocal的实现原理」?如下,最好是能结合以上结构图一起说明哈~ ❝ Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,即每个线程都有一个属于自己的ThreadLocalMap。ThreadLocalMap内部维护着Entry数组,每个Entry代表一个完整的对象,key是ThreadLocal本身,value是ThreadLocal的泛型值。每个线程在往ThreadLocal里设置值的时候,都是往自己的ThreadLocalMap里存,读也是以某个ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离。 ❞ ThreadLocal 内存泄露问题 先看看一下的TreadLocal的引用示意图哈, ThreadLocalMap中使用的 key 为 ThreadLocal 的弱引用,如下 ❝ 弱引用:只要垃圾回收机制一运行,不管JVM的内存空间是否充足,都会回收该对象占用的内存。 ❞ 弱引用比较容易被回收。因此,如果ThreadLocal(ThreadLocalMap的Key)被垃圾回收器回收了,但是因为ThreadLocalMap生命周期和Thread是一样的,它这时候如果不被回收,就会出现这种情况:ThreadLocalMap的key没了,value还在,这就会「造成了内存泄漏问题」。 如何「解决内存泄漏问题」?使用完ThreadLocal后,及时调用remove()方法释放内存空间。 ThreadLocal的应用场景 数据库连接池 会话管理中使用 3. synchronized和ReentrantLock的区别? 我记得校招的时候,这道面试题出现的频率还是挺高的~可以从锁的实现、功能特点、性能等几个维度去回答这个问题, 「锁的实现:」 synchronized是Java语言的关键字,基于JVM实现。而ReentrantLock是基于JDK的API层面实现的(一般是lock()和unlock()方法配合try/finally 语句块来完成。) 「性能:」 在JDK1.6锁优化以前,synchronized的性能比ReenTrantLock差很多。但是JDK6开始,增加了适应性自旋、锁消除等,两者性能就差不多了。 「功能特点:」 ReentrantLock 比 synchronized 增加了一些高级功能,如等待可中断、可实现公平锁、可实现选择性通知。 ❝ ReentrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。synchronized与wait()和notify()/notifyAll()方法结合实现等待/通知机制,ReentrantLock类借助Condition接口与newCondition()方法实现。ReentrantLock需要手工声明来加锁和释放锁,一般跟finally配合释放锁。而synchronized不用手动释放锁。 ❞ 4. 说说CountDownLatch与CyclicBarrier区别 CountDownLatch:一个或者多个线程,等待其他多个线程完成某件事情之后才能执行; CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行。 举个例子吧: ❝ CountDownLatch:假设老师跟同学约定周末在公园门口集合,等人齐了再发门票。那么,发门票(这个主线程),需要等各位同学都到齐(多个其他线程都完成),才能执行。CyclicBarrier:多名短跑运动员要开始田径比赛,只有等所有运动员准备好,裁判才会鸣枪开始,这时候所有的运动员才会疾步如飞。 ❞ 5. Fork/Join框架的理解 ❝ Fork/Join框架是Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。 ❞ Fork/Join框架需要理解两个点,「分而治之」和「工作窃取算法」。 「分而治之」 以上Fork/Join框架的定义,就是分而治之思想的体现啦 「工作窃取算法」 把大任务拆分成小任务,放到不同队列执行,交由不同的线程分别执行时。有的线程优先把自己负责的任务执行完了,其他线程还在慢慢悠悠处理自己的任务,这时候为了充分提高效率,就需要工作盗窃算法啦~ 工作盗窃算法就是,「某个线程从其他队列中窃取任务进行执行的过程」。一般就是指做得快的线程(盗窃线程)抢慢的线程的任务来做,同时为了减少锁竞争,通常使用双端队列,即快线程和慢线程各在一端。 6. 为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法? 看看Thread的start方法说明哈~ /** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ public synchronized void start() { ...... } 复制代码 JVM执行start方法,会另起一条线程执行thread的run方法,这才起到多线程的效果~ 「为什么我们不能直接调用run()方法?」 如果直接调用Thread的run()方法,其方法还是运行在主线程中,没有起到多线程效果。 7. CAS?CAS 有什么缺陷,如何解决? CAS,Compare and Swap,比较并交换; ❝ CAS 涉及3个操作数,内存地址值V,预期原值A,新值B; 如果内存位置的值V与预期原A值相匹配,就更新为新值B,否则不更新 ❞ CAS有什么缺陷? 「ABA 问题」 ❝ 并发环境下,假设初始条件是A,去修改数据时,发现是A就会执行修改。但是看到的虽然是A,中间可能发生了A变B,B又变回A的情况。此时A已经非彼A,数据即使成功修改,也可能有问题。 ❞ 可以通过AtomicStampedReference「解决ABA问题」,它,一个带有标记的原子引用类,通过控制变量值的版本来保证CAS的正确性。 「循环时间长开销」 ❝ 自旋CAS,如果一直循环执行,一直不成功,会给CPU带来非常大的执行开销。 ❞ 很多时候,CAS思想体现,是有个自旋次数的,就是为了避开这个耗时问题~ 「只能保证一个变量的原子操作。」 ❝ CAS 保证的是对一个变量执行操作的原子性,如果对多个变量操作时,CAS 目前无法直接保证操作的原子性的。 ❞ 可以通过这两个方式解决这个问题: ❝ 使用互斥锁来保证原子性;将多个变量封装成对象,通过AtomicReference来保证原子性。 ❞ 有兴趣的朋友可以看看我之前的这篇实战文章哈~ CAS乐观锁解决并发问题的一次实践[2] 8. 如何保证多线程下i++ 结果正确? 使用循环CAS,实现i++原子操作 使用锁机制,实现i++原子操作 使用synchronized,实现i++原子操作 没有代码demo,感觉是没有灵魂的~ 如下: /** * @Author 捡田螺的小男孩 */ public class AtomicIntegerTest { ​ private static AtomicInteger atomicInteger = new AtomicInteger(0); ​ public static void main(String[] args) throws InterruptedException { testIAdd(); } ​ private static void testIAdd() throws InterruptedException { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); for (int i = 0; i < 1000; i++) { executorService.execute(() -> { for (int j = 0; j < 2; j++) { //自增并返回当前值 int andIncrement = atomicInteger.incrementAndGet(); System.out.println("线程:" + Thread.currentThread().getName() + " count=" + andIncrement); } }); } executorService.shutdown(); Thread.sleep(100); System.out.println("最终结果是 :" + atomicInteger.get()); } } 复制代码 运行结果: ... 线程:pool-1-thread-1 count=1997 线程:pool-1-thread-1 count=1998 线程:pool-1-thread-1 count=1999 线程:pool-1-thread-2 count=315 线程:pool-1-thread-2 count=2000 最终结果是 :2000 复制代码 9. 如何检测死锁?怎么预防死锁?死锁四个必要条件 死锁是指多个线程因竞争资源而造成的一种互相等待的僵局。如图感受一下: 「死锁的四个必要条件:」 互斥:一次只有一个进程可以使用一个资源。其他进程不能访问已分配给其他进程的资源。 占有且等待:当一个进程在等待分配得到其他资源时,其继续占有已分配得到的资源。 非抢占:不能强行抢占进程中已占有的资源。 循环等待:存在一个封闭的进程链,使得每个资源至少占有此链中下一个进程所需要的一个资源。 「如何预防死锁?」 加锁顺序(线程按顺序办事) 加锁时限 (线程请求所加上权限,超时就放弃,同时释放自己占有的锁) 死锁检测 怎么样,这几道题你遇到了能回答多少? 而这,只是常见的多线程,高并发以及jvm调优的源码问题中最常见的几道面试题,其他的面试题我已经整理到我的git仓库中,并在不断地更新上传中 相应的文章已经整理形成文档,git扫码获取资料看这里 https://gitee.com/biwangsheng/personal.git

优秀的个人博客,低调大师

Hadoop大数据平台环境搭建注意事项,波若分布式数据采集工具功能剖析,数道云

Hadoop大数据作为时代发展的产物,影响着互联网企业发展、以及企业关于品牌形象推广、政府有关民意采集、以及有关数据信息收集分类……………… Hadoop技术的发展,带来了海量数据高效处理的能力,也给互联网政企、高校的发展带来了突破性的发展。互联网的数据容量巨大,以10-100GB或更多,数据种类多种多样。如何利用Hadoop大数据平台实现大数据的快捷处理呢?以及Hadoop环境搭建注意事项分析。 Hadoop大数据平台选择注意事项: 1.环境的部署和搭建 前期准备:网络环境的搭建、Hadoop环境的部署、需要下载或者安装的Hadoop程序、虚拟机、java JDK环境部署…… 2.集群环境部署 (1)电脑配置(适用于多少台虚拟机同时上线) (2)什么样的虚拟机适用于Hadoop集群环境使用 (3)关于大数据平台搭建系统的选择及使用 (4)了解熟悉安装过程 (5)选择适合的安装模式 3.产品的使用及操作 (1)登录管理界面 (2)启动安装导向 (3)设置集群名称 (4)安装选项,输入集群节点主机名列表 (5)根据需求,选择相对应的服务项目 (6)根据步骤,如果有需要,可以进行定制开发选项 (7)安装完成 (8)功能使用测试

优秀的个人博客,低调大师

即将到来的金三银四,这10道springboot常见面试题你需要了解下

1.什么是Spring Boot? 多年来,随着新功能的增加,spring变得越来越复杂。只需访问https://spring.io/projects页面,我们就会看到可以在我们的应用程序中使用的所有Spring项目的不同功能。 如果必须启动一个新的Spring项目,我们必须添加构建路径或添加Maven依赖关系,配置应用程序服务器,添加spring配置。 因此,开始一个新的spring项目需要很多努力,因为我们现在必须从头开始做所有事情。 Spring Boot是解决这个问题的方法。Spring Boot已经建立在现有spring框架之上。使用spring启动,我们避免了之前我们必须做的所有样板代码和配置。 因此,Spring Boot可以帮助我们以最少的工作量,更加健壮地使用现有的Spring功能。 2.Spring Boot有哪些优点? · 减少开发,测试时间和努力。 · 使用JavaConfig有助于避免使用XML。 · 避免大量的Maven导入和各种版本冲突。 · 提供意见发展方法。 · 通过提供默认值快速开始开发。 · 没有单独的Web服务器需要。这意味着你不再需要启动Tomcat,Glassfish或其他任何东西。 · 更少的配置 因为没有web.xml文件。只需添加用@ Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前 一样对其进行管理。您甚至可以将@Autowired添加到bean方法中,以使Spring自动装入需要的依赖关系中。 · 基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring将在(application{environment} .properties)中加载后续的应用程序属性文件。 3.什么是JavaConfig? Spring JavaConfig是Spring社区的产品,它提供了配置Spring IoC容器的纯Java方法。因此它有助于避免使用XML配置。使用JavaConfig的优点在于: 面向对象的配置。由于配置被定义为JavaConfig中的类,因此用户可以充分利用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。 减少或消除XML配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在XML和Java之间来回切换。 JavaConfig为开发人员提供了一种纯Java方法来配置与XML配置概念相似的Spring容器。 从技术角度来讲,只使用JavaConfig配置类来配置容器是可行的,但实际上很多人认为将JavaConfig与XML混合匹配是理想的。 类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java 5.0对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找。 4.如何重新加载Spring Boot上的更改,而无需重新启动服务器? 这可以使用DEV工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat将重新启动。 Spring Boot有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。 开发人员可以重新加载Spring Boot上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot在发布它的第一个版本时没有这个功能。 这是开发人员最需要的功能。DevTools模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供H2数据库控制台以更好地测试应用程序。 5.Spring Boot中的监视器是什么? Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。 有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态。 6.如何在Spring Boot中禁用Actuator端点安全性? 默认情况下,所有敏感的HTTP端点都是安全的,只有具有ACTUATOR角色的用户才能访问它们。 安全性是使用标准的HttpServletRequest.isUserInRole方法实施的。 我们可以使用management.security.enabled = false 来禁用安全性。只有在执行机构端点在防火墙后访问时,才建议禁用安全性。 如何在自定义端口上运行Spring Boot应用程序? 为了在自定义端口上运行Spring Boot应用程序,您可以在application.properties中指定端口。 server.port = 8090 7.什么是YAML? YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 8.如何实现Spring Boot应用程序的安全性? 为了实现Spring Boot的安全性,我们使用 spring-boot-starter-security依赖项,并且必须添加安全配置。它只需要很少的代码。配置类将必须扩展WebSecurityConfigurerAdapter并覆盖其方法。 9.如何集成Spring Boot和ActiveMQ? 对于集成Spring Boot和ActiveMQ,我们使用spring-boot-starter-activemq 依赖关系。 它只需要很少的配置,并且不需要样板代码。 10.如何使用Spring Boot实现分页和排序? 使用Spring Boot实现分页非常简单。使用Spring Data-JPA可以实现将可分页的org.springframework.data.domain.Pageable传递给存储库方法。

优秀的个人博客,低调大师

【阿里鬼道】Weex在双11会场的大规模应用:业务支撑、稳定性保障和秒开实战

前言 Native开发的诸多亮点中,流畅体验和系统调用是最多被提及的。流畅体验体现在页面滚动/动画的流畅性,背后是更好的内存管理和更接近原生的性能;同时又是Web的痛点:资源首次下载、长页面内存溢出和滚动性能、动画性能、传统web性能(如JS执行效率)。Native有丰富的系统调用能力,而Web痛点在于:W3C标准太慢,有限的设备访问能力,API兼容性问题较严重,如Geolocation在AndroidWebview中可用性很差。 Web开发同样有诸多亮点,其中最耀眼的当属发布能力和规模协作。NativeApp商店审核周期长(尤指iOS);应用更新周期长,iOS稍快大概能达到一周更新率60%-80%,Android同样的更新率要2周甚至更长。而Web在合适的缓存机制下一分钟可达到99

优秀的个人博客,低调大师

它一本正经地骗了你:WorkBuddy也会“胡说八道”,3招让它句句有出处

前两天,一位读者在后台留言,语气里带着点后怕:他用 WorkBuddy 写一份工作汇报,让 AI “帮我补几个行业数据撑撑场面”。AI 很给力,唰唰给了五六个“权威数据”,还标了“来源:某研究院”。他美滋滋粘进材料,结果开会时被领导一句话戳穿——那个研究院那年根本没发过这报告,数据纯属虚构。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册