面试必备:多线程学习(一)

这是2020年“水”的第23篇文章

面试中,多线程并发问题基本上是必问的,所以,不背上个线程相关的问题,都不好意思出去面试了。

一提到多线程,相信大部分小伙伴首先想到的一定是 SynchronizeLock,再就是volatileconcurrent并发包,厉害点的小伙伴呢,还能再跟面试官吹吹Synchronizevolatile的区别跟原理,以及并发包常用的数据结构,例如之前提到的 ConcurrentHashMap

好了,废话不多说,本篇就以面试为出发点,看看多线程到底要准备哪些傻吊知识点。

1、多线程的创建方式

  1. 继承Thread
  2. 实现Runnable接口
  3. 实现Callable接口

一共3种创建方式,不要问哪个好,问就是接口形式的好,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心,但是,是选择实现Runnable,还是Callable,就要根据自己情况选择了。

延伸补充:Runnable跟Callable区别?

如果上边的问题回答了Runnable、Callable,那么就要准备好关于两者的区别?什么?没用过Callable?背就完事了。

Runnable没有返回值,需要做的事情就是去执行run()方法,执行完就完了。
Callable有返回值,该返回值是Callable接口中的call()方法,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

简单看一下代码:

Callable callable = new Callable() {
  @Override
  public String call() throws Exception 
{
      Thread.sleep(5000);
      return "我是call方法返回值";
  }
};
Future future = executor.submit(callable);
System.out.println("获取返回值: "+future.get());

看完上方代码,如果问到Callable接口会有哪些应用场景应该会答了吧?

2、wait() 和 notify() 的理解和使用?

有时候面试官会先延伸一下它的出处,比如,你能说一下Object类都有哪些方法吗?

只要你提到了 wait() 跟 notify() || notifyAll() 那么基本就会问相关的内容了。

wait和notify是用来让线程进入等待状态以及使线程唤醒的两个操作。

理解:

wait、notify 属于 Object 基础类,所以每个对象都有 wait、notify 的功能,也就是每个对象都有锁的权利;但是在使用此类方法的时候,一定要对竞争资源进行加锁操作,获得这个锁对象的控制权,比如放在 Synchronize(obj) 代码块中,如果不加锁的话,则会报 IllegalMonitorStateException 异常。

使用:

public class Test {

    public static void main(String[] args{
        Object obj = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (obj) {
                try {
                    System.out.println("1-before wait");
                    obj.wait();
                    System.out.println("1-after wait");
                } catch (Exception e) {
                    System.out.println(String.format("1-catch :%s. interrupt状态: %s",e.toString(),Thread.currentThread().isInterrupted()));
                    Thread.currentThread().interrupt();
                    System.out.println("设置标志位后interrupt状态: "+ Thread.currentThread().isInterrupted());

                }
            }
        });

        thread1.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println("线程初始interrupt状态:"+thread1.isInterrupted());
        thread1.interrupt();

    }
}

如果你不太清楚上方代码中的 interrupt()、interrupted() 和isInterrupted() 那么可以参考这篇文章:Thread类中interrupt方法详解

废话总结:

wait和notify来自于Object基础类;
wait和notify是用来让线程进入等待状态以及使线程唤醒的两个操作。
wait或notify方法,使用时必须保证当前运行的线程取得了该对象的控制权。
如果在没有控制权的线程里执行wait或notify方法,会报IllegalMonitorStateException异常。

3、sleep() 和 wailt() 的区别

如果在上一个wailt、notify中没有回答出wailt的细节的话,那么这个问题就会常问;

首先两者来源不同,sleep来自Thread类,而wait来自Object类。

sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,而wait方法会放弃这个对象的监视器,怎么讲?

sleep方法不会释放锁,调用sleep后不会出让系统资源,典型无赖行为「占着茅坑不拉*」;而wait则是进入线程等待池等待,会出让系统资源,其他线程可以占用CPU,就是我现在不用了,你们先用吧。

通常wait是不会加时间限制的,因为如果wait线程的运行资源不够,即使出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待系统分配资源。

而sleep(秒)可以用指定时间使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。比如上端代码中我用到了 thread1.interrupt(); 方法,作用就是强行打断。

使用范围不同:wait只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。所以你看到的只要出现wait必出现Synchronize,而sleep可以到处使用。

废话总结:

所属类不同:sleep() 来自Thread;wailt() 来自 Object
是否释放锁:sleep() 不会释放锁;wailt() 会释放锁
用法不同:sleet时间到了会自动恢复;wailt() 可以使用notigy()/notigyAll()直接唤醒
使用范围不同:sleep() 在任何地方可用;wait() 需要结合 Synchronize使用
作用不同:sleep() 通常被用于暂停执行;wait() 通常被用于线程间交互/通信

4、如何保证多线程安全?

  1. 使用安全类,比如 java.util.concurrent 并发包下的类;
  2. 使用锁,比如自动Synchronize,手动锁 Lock

如上两点只是尽量做到线程安全,或者说目前被建议以及常用的,但做到绝对的线程安全通常需要付出许多额外代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet

废话总结:

如果你的代码,在多线程下执行和在单线程下执行,永远都能得到一样的结果,那么你的代码就是线程安全的。

5、Synchronize跟Lock区别

提到Synchronize就不得不扯上Lock,冤家路窄,面试总是会问。

Synchronize:java中提供的一个并发控制的关键字,自动锁、重量级。主要用在同步方法和同步代码块中,也就是说,synchronized既可以修饰方法也可以修饰代码块。被synchronized修饰的代码块及方法,在同一时间,只能被单个线程访问。应用场景:商品下单,商品库存的修改。

Lock:是一个类,确切说是一个接口类,其实现类可以实现同步访问。Lock为轻量级、手动锁,能够实现synchronized所实现的功能,但Lock相对更加灵活,可以被继承、可以有方法、可以有各种各样的类变量。

转自网上的区别表格:

类别synchronizedLock
存在层次Java的关键字,在jvm层面上是一个类
锁的释放1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁在finally中必须释放锁,不然容易造成线程死锁
锁的获取假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态无法判断可以判断
锁类型可重入 不可中断 非公平可重入 可判断 可公平(两者皆可)
性能少量同步大量同步

个人补充:

如果单单写两者,完全可以写一篇文章,由于本篇是出于面试准备的,所以面试官问到时,简单说一下两者的作用,以及各自的应用场景即可『经验初级』,当然,如果你有特地看过源码的话,自然是建议你引导面试官问你原理,你懂得~ 不过话说回来,synchronized 原理还是有必要了解的~

废话总结:

1、Synchronized为java关键字,由JVM控制;Lock为接口类,由JDK实现;
2、Synchronized重量级、自动锁,Lock轻量级、手动锁;
3、发生异常时,Synchronized会自动释放锁,Lock需要手动在finally释放锁,不释放很容易造成死锁;
4、Lock更加灵活,能够响应中断,让等待状态的线程停止等待,synchronized不行;
5、通过Lock可以知道线程是否成功获得了锁,synchronized不行;

最后

本篇为多线程面试准备的第一篇,标签为左侧分栏的:面试相关

目前只准备了5个小问题,会结合自己近期的准备持续更新下一篇。

博客地址:https://www.cgblog.com/niceyoo

如果觉得这篇文章有丶东西,不防关注一下我,关注是对我最大的鼓励~

18年专科毕业后,期间一度迷茫,最近我创建了一个公众号用来记录自己的成长。

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

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

相关文章

[js] 请使用 js 实现一个双向链表

[js] 请使用 js 实现一个双向链表 链表结构是我们在面试中经常会被问起的较为基础的数据结构问题,起初学习数据结构使用的是C语言,最近在做前端面试题的过程中没碰到了需要用js实现双链表的需求,百度出来的文章发现可很多错误,于…

MacOS中Nginx的安装「借助Homebrew」

本文Nginx的安装借助于Homebrew; 1、Homebrew2、Nginx安装 1、Homebrew 如果你已经安装过Homebrew了,那么你可以跳过这一步,直接进行Nginx安装步骤; Homebrew是一款MacOS平台下的软件包管理工具,拥有安装、卸载、更新、…

03、动态代理--CGLib引入增强

package com.offer.note.Java基础.动态代理.CGLib引入增强;public interface Browser {void visitInternet(); } package com.offer.note.Java基础.动态代理.CGLib引入增强;/*** 目标类:被代理类** author: xueguanfeng* date: 2018-05-15 09:57*/ public class Chr…

[js] ajax请求地址只支持http/https吗?能做到让它支持rtmp://等其它自定义协议吗 ?

[js] ajax请求地址只支持http/https吗?能做到让它支持rtmp://等其它自定义协议吗 ? ajax只支持http/https协议, 可以通过自定义http头来间接支持自定义协议个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易&#xf…

面试必备:HashMap底层数据结构?jdk1.8算法优化,hash冲突,扩容等问题

面试必备系列不会长篇理论求证&#xff0c;直接上答案&#xff0c;仅供参考&#xff0c;不喜勿喷。 1、能说说HashMap的底层原理吗&#xff1f; HashMap<String,String> map new HashMap<String,String>(); map.put(“key”,”value”); [<key1,value1>,<…

[js] 请写一个性能最好的深度克隆对象的方法

[js] 请写一个性能最好的深度克隆对象的方法 const deepClone (obj) > {const copy obj instance Array ? [] : {};for (let key in obj) {if (obj.hasOwnProperty(key)) {copy[key] typeof obj[key] object ? deepClone(obj[key]) : obj[key]}} return copy; }个人简…

快速下载||AnotherRedisDesktopManagerMedis-Redis可视化工具

尽管是在Gitee上下载这款软件&#xff0c;网速仍然是非常的慢&#xff0c;不知道是不是我的网络问题。 提供一份我的下载链接 MacOS&#xff1a;Another.Redis.Desktop.Manager.1.3.1.dmg Windows&#xff1a;Another.Redis.Desktop.Manager.1.3.1.exe 也许你还想试试Medis Mac…

[js] 使用ajax请求真的不安全吗?为什么?

[js] 使用ajax请求真的不安全吗&#xff1f;为什么&#xff1f; AJAX是发送HTTP请求的一种方式&#xff0c;只不过浏览器给它加了一个同源策略而已。 所以从这一点可以得出一个结论&#xff1a;AJAX本质上安全性和HTTP请求一样个人简介 我是歌谣&#xff0c;欢迎和大家一起交…

面试必备:synchronized的底层原理?

最近更新的XX必备系列适合直接背答案&#xff0c;不深究&#xff0c;不喜勿喷。 你能说简单说一下synchronize吗&#xff1f; 可别真简单一句话就说完了呀~ 参考回答&#xff1a; synchronize是java中的关键字&#xff0c;可以用来修饰实例方法、静态方法、还有代码块&#xff…

hadoop fs 命令详解

转载: https://blog.csdn.net/bgk083/article/details/49454209转载于:https://www.cnblogs.com/water-green/p/9050122.html

数组追加数组,小程序数组里面追加数组如何操作?

由于写错小程序生命周期函数方法名称「onLoad > onload」&#xff0c;一直以为自己用错了push… 需求描述 var arr[];var value [ a,b,c,d ]; 已有数组arr&#xff0c;获取的数据形式为数组value&#xff0c;需要将value追加值arr数组中&#xff0c;即[[],[]] 尝试过程 1、…

[js] 你有使用过pjax吗?它的原理是什么?

[js] 你有使用过pjax吗&#xff1f;它的原理是什么&#xff1f; pushState ajax pjax个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

Python3回文相关算法小结

[本文出自天外归云的博客园] 总结一下关于回文相关的算法&#xff1a; 判断字符串本身是否是回文返回字符串中的所有子串找到字符串中包含的所有回文判断字符串中是否包含回文将字符串变成一个不包含回文的字符串代码如下&#xff1a; # 判断字符串本身是否是回文 def is_huiwe…

面试必备:CAS无锁机制

CAS无锁机制原理&#xff0c;面试高频问题之一&#xff0c;其实&#xff0c;日常开发中并不会直接使用CAS无锁机制&#xff0c;都是通过一系列封装好的工具类来使用&#xff0c; 说不定面试官不提问&#xff0c;都不知道有这么个东西存在。 1、能说一下你对CAS的理解吗&#xf…

[js] 根据元素ID遍历树形结构,查找到所有父元素ID

[js] 根据元素ID遍历树形结构&#xff0c;查找到所有父元素ID var list [{ "orgId": 1, "orgName": "校长办公室1", "parentId": 0 },{ "orgId": 2, "orgName": "校长办公室2", "parentId"…

安装oracle和plsql心得

最近给两台裸机安装oracle&#xff0c;plsql&#xff0c;java运行环境等相关。从中分享一些小心得。 1.oracle安装&#xff0c;基本都是安装ORACLE11g的&#xff0c;中途遇到报错了是因为64位windows系统&#xff0c;需要重新拷贝对应文件夹到对应文件下。 2.plsql安装的话&…

[js] 举例说明Object.defineProperty会在什么情况下造成循环引用导致栈溢出?

[js] 举例说明Object.defineProperty会在什么情况下造成循环引用导致栈溢出&#xff1f; var data {count: 1,value: 2 } Object.defineProperty(data, count, {enumerable: true,configurable: true,get: function () {console.log(你访问了count, this.count); // 循环读取…

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})注解作用

有小伙伴在群里问到对 SpringBootApplication(exclude { DataSourceAutoConfiguration.class}) 有点疑惑&#xff0c;故记之。 exclude&#xff0c;排除此类的AutoConfig&#xff0c;即禁止 SpringBoot 自动注入数据源配置&#xff0c;怎么讲&#xff1f; DataSourceAutoConfi…

[js] 写一个方法,当给定数字位数不足8位时,则在左边补充0以补足8位数的方法

[js] 写一个方法&#xff0c;当给定数字位数不足8位时&#xff0c;则在左边补充0以补足8位数的方法 function padNumber(n, targetLen, placeholder) {const arr ("" n).split("");const diff arr.length - targetLen;if (diff < 0) {return Array(…

小程序json字符串取值问题,怎么取出来的是undefined,eval函数不能用?

1、后端返回的值 "{\"msg\":\"InvalidParameterValue.NoFaceInPhoto-图片中没有人脸。\",\"code\":500}” 关于为何会返回如上json字符串的场景&#xff1a;文件上传「声明了Content-Type」 wx.uploadFile({ url: common.apiServerwx/user…