• 14
  • 14
分享
  • 十个多线程并发编程面试题(附答案)——软件测试圈
  • 北极 2021-03-05 14:39:29 字数 2863 阅读 2531 收藏 14

1.说说你知道的创建线程的方式

  • 继承Thread类,重写run方法。

  • 实现Runnable接口,重写run方法。

  • 实现Callable接口,重写call方法。

  • 通过线程池创建线程。

2.说说Runnable和Callable的区别

  • Callable可以返回一个类型V,而Runnable不可以。Callable能够抛出checked exception,而Runnable不可以。

  • Future和FutureTask留给你们!我放GitHub上了(uphe)

3.说说通过线方程池创建线程的式

  • Executors.newCachedThreadPool();创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

  • Executors.newFixedThreadPool(10);创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • Executors.newScheduledThreadPool(10);创建一个定长线程池,支持定时及周期性任务执行。

  • Executors.newSingleThreadExecutor();创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

  • 阿里巴巴开发手册上不推荐上面的创建方式,创建线程池推荐用ThreadPoolExecutor,其中ThreadPoolExecutor有七大参数,四大拒绝策略。

  1. int corePoolSize 核心线程池大小。

  2. int maximumPoolSize 最大核心线程池大小。

  3. long keepAliveTime 超时存活时间。

  4. TimeUnit unit 超时单位。

  5. BlockingQueue workQueue 阻塞队列。

  6. ThreadFactory threadFactory 线程工厂,用于创建线程。

  7. RejectedExecutionHandler handler 拒绝策略。

四大拒绝策略,这里通过银行办理业务的例子进行说明。

  1. AbortPolicy()); 银行满了还有人进来,不处理,抛出异常(默认)。

  2. CallerRunsPolicy(); 银行满了,不处理,哪里来的去哪里,一般抛给main线程。

  3. DiscardPolicy(); 银行满了,把该线程丢掉,不抛异常。

  4. DiscardOldestPolicy(); 银行满了,会和先来的线程竞争,不抛异常。

4.最大线程数是如何确定的呢

一般有两种策略CPU密集型和IO密集型,所谓CPU密集型,也就是,几核的CPU就定义为几,我的是八核,所以定义为8

Runtime.getRuntime().availableProcessors();

获取CPU的核数,IO密集型,就是判断程序中有多少个非常耗IO线程的程序,最大线程池的大小要大于这个值即可。

5.说说synchronized和Lock的区别

  • synchronized是关键字,Lock是类。

  • synchronized无法获取锁的状态,Lock可以。

  • synchronized会自动释放锁,Lock需要手动。

  • synchronized没有Lock锁灵活(Lock锁可以自己定制)。

6.说说ReentrantLock的应用场景

  • ReentrantLock默认是非公平锁,但它可以设置公平锁,也就是谁先来的谁先获得锁new ReentrantLock(true)。

  • ReentrantLock可以响应中断,也就是当两个线程发生死锁的时候,你把A线程中断了,B线程可以正常运行。

  • ReentrantLock可以通过tryLock()实现限时等待,这样可以解决死锁问题。

7.synchronized锁的优化了解吗

  • synchronized在JDK1.6进行了锁的优化,也就是当一个线程多次访问一个同步代码块的时候,此时会记录该线程的threadId也就是,当你再来访问的时候,我就只需判断threadId就行了,效率高,这属于偏向锁。

  • 当有多个线程来的时候,那么这个锁就会升级为轻量级锁,也就是通过CAS,来进行尝试获取锁,是一种自旋锁的状态。如果在短时间内可以获得锁,不会堵塞,而且节约了CUP上下文切换的时间。

  • 如果长时间没有获取到锁,会消耗CUP的资源,因为在那一直死循环,经过一个时间段后会升级为重量级锁,会发生阻塞。其中锁升级是不可逆的。

8.说说对volatile关键字的理解

  • 三大特性保证可见性,不保证原子性,禁止指令重排。

  • 在说volatile之前,需要讲解一个东西,Java内存模型(Java Memory Model,JMM),当线程读取内存中的一个变量时,会先把这个变量拷贝到CPU的高速缓存区,然后对其进行操作,操作完成后,会把该变量写入到内存中。在单线程中是不会出现任何问题的,但是在多线程中就会有问题,当线程1读取了该变量a=1到缓存区进行了加1操作,还没写到内存中,线程2读取了内存中的变量a=1也进行加1操作,然后线程1写入内存a=2,线程2也写入a=2到内存,那么最后,该变量的值是2,而不是3(出现了线程安全问题)。

  • 我们想要当线程1进行了加1操作之后,让线程2知道,这就是volatile的作用了,可以保证可见性,也就是,当线程1对a变量进行了加1操作,会直接写入到内存中(立即马上),并且通知线程2,变量被修改了,要求线程2缓冲区的值去内存中重新读取。但是,加1操作不是原子性的(三步,首先读取a变量的值,然后对其进行加1操作,然后赋值给a),也就是说,当线程1读取a变量到缓冲区后,还没有修改a的值,此时线程2进来了,读取了a的值,并且对其进行了加1操作,由于可见性,会把线程1缓冲区的值进行修改,但是,线程1中的CPU已经读取了缓冲区的值,而且是更新前的值,所以出现了线程安全问题,也是volatile不保证原子性的问题。于是就需要加1操作是原子性操作,于是就有了一个automic包,通过该包下的方法,可以实现加1的原子性操作(还有其他原子性操作)。

  • 所谓指令重排,也就是在不影响单线程程序程序结果的情况下进行最优执行排序

9.那你说说CAS吧

  • CAS(Compare And Swap,比较并交换),如果我们想要修改某个值num,那么我们可以通过一个方法compareAndSet(5,6)意思是,我们期望num的值是5,如果是,就修改为6。但是这就会有一个问题,我们期望的num是5,如果有其他线程把5修改为了8,然后又修改为了5,最终是5,但是已经被修改过一次了,这就是ABA问题。我们可以通过AtomicStampedReference,也就是原子引用,在创建的时候,有一个印记,相当于版本号,每被修改一次,版本号都被更新,所以,当出现ABA问题的时候,我们就可以清楚的知道,被修改了多少次。


作者:贺贺学编程

原文链接:https://blog.csdn.net/HeZhiYing_/article/details/113717117


  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 作者:优测团队测试专家杨余超 背景介绍       近日优测测试服务团队在进行某客户PC端产品整体测试的过程中,也涉及到PC性能测试部分。本文将结合该项目实际经验,总结如何应用本地监控性能的方案进行PC性能测试。本文内容主要为监控CPU、内存、网络以及GPU的性能使用状况等,重点介绍监控项目的定义及相关结果判定的准则。对于性能监控的实现方法也注明了实现步骤,方便测试同仁进行参照。    CPU 内存 网络1、Windows开始菜单→Windows管理工具→性能监视器。 2、点...
            0 0 2417
            分享
          •   一、 功能测试  1. 点击分享按钮正确跳转分享页面,展示可分享的app,并进行分享跳转。  2. 页面默认展示自定义可分享app,有按钮支持更多app选择,过滤部分系统应用app。  3. 点击app分享,校验是否支持分享后打开链接。  4. 点击链接,其内容是否和原来的一致。  5. 是否支持取消分享。  6. 分享内容失败时,是否返回失败信息。  7. 分享内容成功,可选择留在app应用内还是返回浏览器。  8. 分享内容成功后,进入app可看到分享以链接形式展现, 展现内容为搜索标题以及搜索内容,无错别字布局合理。  9. 点击分享链接可进入浏览器展示链接内容。  二、容...
            0 0 384
            分享
          • 1、JMeter简介JMeter是Apache组织开发的基于Java的压力测试工具。具有开源免费、框架灵活、多平台支持等优势。除了压力测试外,JMeter在接口测试方面也有广泛的应用。2、JMeter安装访问JMeter官网:https://jmeter.apache.org/download_jmeter.cgi,点击下载后解压缩,依次打开\apache-jmeter-4.0\JMeter\bin,运行jmeterw.cmd即可。(建议在桌面创建jmeterw.cmd的快捷方式,方便快速打开)3、使用JMeter完成单个接口测试3.1 添加线程组在“测试计划”上点击鼠标右键-->添加-...
            12 12 3605
            分享
          •   一个新人进入一个新的体系,有必要建立一个框架结构的思维方式,我就来尝试给你搭搭框架,并且尽量使用比较通俗的表达方式。  质量管理工作分为哪些部分?  首先我用一张图简单给你说说质量到底是一份怎样的工作,主要分哪几块内容:可能很多业内人士看到要说我的区分方式太简单粗暴了,但是过于细化对于初学者来说可能根本就看不懂,另外我没有把领导职能加入进去  既然做质量你必须搞清楚你现在是做实物还是做体系,一个简单的区分方法(注意:不是很科学,但是对于新人来说比较容易理解)就是,实物的主要工作面向产品和过程,体系的主要工作面向流程和审核。  一个新人加入了质量部的大团队以后,如果有得选那么我的建议是先走实...
            0 0 398
            分享
          • 1、软件测试的目的是发现软件中存在的错误,提高软件质量,降低软件项目的风险。2、软件测试只能证明软件存在错误,而不能证明软件没有错误。测试的目的只是把软件的错误控制在一个可以进行产品交付/发布的程度上,可以交付/发布产品并不是没有错误的产品。3、软件测试不可能无休止的进行下去。随着测试时间的延伸,发现错误的成本会越来越大,这就需要测试有度,而这个度并不能由项目计划实际判断,而是要根据测试发现错误的概率来判断。4、第三方测试指独立于软件公司自身测试的测试,所谓第三方是指在软件公司和软件用户之间的一方,是一个中介的服务机构,第三方测试除了发现软件问题之外,还要对软件进行科学、公正的评价的职能。5、...
            12 14 5372
            分享
      • 51testing软件测试圈微信