如果你即将去一家从事大型系统研发的公司进行Java面试,不可避免的会有多线程相关的问题。下面是一些针对初学者或者新手的问题,如果你已经具备良好的基础,那么你可以跳过本文,直接尝试针对进阶水平的Java多线程编程问题及解答。

关联链接: Java multi-threading-1 | Java multi-threading-2

问题:进程和线程的区别 解答:一个进程对应一个程序的执行,而一个线程则是进程执行过程中的一个单独的执行序列,一个进程可以包含多个线程。线程有时候也被称为轻量级进程.

一个Java虚拟机的实例运行在一个单独的进程中,不同的线程共享Java虚拟机进程所属的堆内存。这也是为什么不同的线程可以访问同一个对象。线程彼此共享堆内存并保有他们自己独自的栈空间。这也是为什么当一个线程调用一个方法时,他的局部变量可以保证线程安全。但堆内存并不是线程安全的,必须通过显示的声明同步来确保线程安全。

问题:列举几种不同的创建线程的方法. 解答:可以通过如下几种方式: •  继承Thread 类 •  实现Runnable 接口 •  使用Executor framework (这会创建一个线程池)

 1 class Counter extends Thread {
 2
 3     //method where the thread execution will start
 4     public void run(){
 5         //logic to execute in a thread
 6     }
 7
 8     //let’s see how to start the threads
 9     public static void main(String[] args){
10         Thread t1 = new Counter();
11         Thread t2 = new Counter();
12         t1.start();  //start the first thread. This calls the run() method.
13         t2.start(); //this starts the 2nd thread. This calls the run() method.
14     }
15 }

 1 class Counter extends Base implements Runnable{
 2     //method where the thread execution will start
 3     public void run(){
 4         //logic to execute in a thread
 5     }
 6
 7      //let us see how to start the threads
 8     public static void main(String[] args){
 9         Thread t1 = new Thread(new Counter());
10         Thread t2 = new Thread(new Counter());
11          t1.start();  //start the first thread. This calls the run() method.
12         t2.start();  //this starts the 2nd thread. This calls the run() method.
13     }
14 }

通过线程池来创建更有效率。 相关链接: learn why and how to create pool of  threads using the executor framework

问题:推荐通过哪种方式创建线程,为什么? 解答:最好使用Runnable接口,这样你的类就不必继承Thread类,不然当你需要多重继承的时候,你将一筹莫展(我们都知道Java中的类只能继承自一个类,但可以同时实现多个接口)。在上面的例子中,因为我们要继承Base类,所以实现Runnable接口成了显而易见的选择。同时你也要注意到在不同的例子中,线程是如何启动的。按照面向对象的方法论,你应该只在希望改变父类的行为的时候才去继承他。通过实现Runnable接口来代替继承Thread类可以告诉使用者Counter是Base类型的一个对象,并会作为线程执行。

问题:简要的说明一下高级线程状态. 解答:下图说明了线程的各种状态.

可执行(Runnable):当调用start()方法后,一个线程变为可执行状态,但是并不意味着他会立刻开始真正地执行。而是被放入线程池,由线程调度器根据线程优先级决定何时挂起执行。

1 MyThread aThread = new MyThread();
2 aThread.start();                   //becomes runnable

执行中(Running):处理器已经在执行线程的代码。他会一直运行直到被阻断,或者通过静态方法Thread.yield()自行放弃执行的机会,考虑到场景切换所带来的开销,yield()方法不应该被经常调用。 • 等待中(Waiting):线程由于等待I/O等外部进程的处理结果而处于被阻断的状态,调用currObject.wait( )方法会使得当前线程进入等待状态,直到其它线程调用currObject.notify() 或者currObject.notifyAll() 。 • 睡眠中(Sleeping):重载方法Thread.sleep(milliseconds),Thread.sleep(milliseconds, nanoseconds)可以迫使Java线程进入睡眠状态(挂起)。 • 由于I/O阻塞(Blocked on I/O):当I/O条件发生变化时(例如读取了几个字节的数据)会迁移到可执行状态。 • 由于同步阻塞中(Blocked on synchronization): 当获取锁之后会进入执行中状态。

Thread.State 枚举类型包含了Java虚拟机支持的全部的线程状态类型,下面几点Java的线程宗旨确保了这些线程状态成为可能。 • 对象可以被任何线程共享和修改。 • 线程调度器的抢占性特性,使得线程可以随时在/不在多核处理之间切换处理器内核,这意味着方法可以在执行的过程中切换状态。否则方法中的死循环将永远阻塞CPU,并且使得不同线程的其他方法始终得不到执行。 • 为了防止线程安全问题,那些脆弱的方法或者代码块可以被锁定。这使得线程可以处于被锁定或者加锁请求处理中两种状态。 • 线程在处理I/O资源(如Sockets,文件句柄,数据库连接等)时会进入等待状态, • 处于I/O读写中的线程不能被切换,因此他们或者以成功/失败的结果正常完成处理,或者其它线程关闭了相应的资源,迫使他进入死亡或者完成的状态。这也是为什么一个合理的超时时间可以避免线程由于I/O处理而被永远阻塞,从而导致严重的性能问题。 • 线程可以进入睡眠状态,以使得其他处于等待状态的线程有机会执行。

问题:yield和sleeping有何区别,sleep()和wait()有何区别? 解答:当一个任务调用了yield()方法,它将从执行中状态转变为可执行。而当一个任务调用了sleep(),则将从执行中状态转变为等待中/睡眠中状态。 方法wait(1000)使得当前线程睡眠1秒钟,但调用notify() 或者notifyAll()会随时唤醒线程。而sleep(1000)则会导致当前线程休眠1秒钟。

问题:为什么为了线程安全而锁定一个方法或者一个代码块称为“同步”而不是“锁定”或者“被锁定” 解答:当某个方法或者代码块被声明为”synchronized”后,保存数据的内存空间(例如堆内存)将保持被同步状态。 这意味着:当一个线程获取锁并且执行到已被声明为synchronized的方法或者代码块时,该线程首先从主堆内存空间中读取该锁定对象的所有变化,以确保其在开始执行之前拥有最新的信息。在synchronized部分执行完毕,线程准备释放锁的时候,所有针对被锁定对象的修改都将为写入主堆内存中。这样其他线程在请求锁的时候就可以获取最新的信息。

问题:线程如何进行的同步处理?你可以列举出那些同步级别?同步方法和代码块如何区别? 解答:在Java语言中,每个对象都有一个锁,一个线程可以通过关键字synchronized来申请获取某个对象的锁,关键字synchronized可以被用于方法(粗粒度锁,对性能影响较大)或代码块(细粒度锁)级别。锁定方法往往不是一个很好的选择,取而代之的我们应该只锁定那些访问共享资源的代码块,因为每一个对象都有一个锁,所以可以通过创建虚拟对象来实现代码块级别的同步,方法块级别的锁比锁定整个方法更有效。

Java虚拟机灵活的使用锁和监视器,一个监视器总体来说就是一个守卫者,他负责确保只有一个线程会在同一时间执行被同步的代码。每个监视器对应一个对象的引用,在线程执行代码块的第一条指令之前,他必须持有该引用对象的锁,否则他将无法执行这段代码。一旦他获得锁,该线程就可以进入这段受到保护的代码。当线程不论以何种方式退出代码块时,他都将释放关联对象的锁。对于静态方法,需要请求类级别的锁。

-- 扫描加关注,微信号: importnew --

英文原文:java-success.blogspot,编译:ImportNew-王晓杰

译文地址: http://www.importnew.com/1428.html

【如需转载,请在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】

转载于:https://www.cnblogs.com/dwf07223/p/3226566.html

【转】Java多线程面试问题集锦相关推荐

  1. 想进一线大厂?2021年最详细Java多线程面试问题集锦(含答案),看完可以和面试官扯皮了!

    当我刷到这条脉脉的时候,想到当年老板面试我的时候,拿多线程问题虐我时,想想当时太难了. 悄悄给大家看几道阿里必问的面试题,测测能完美的回答几道呢? 有没有一种一定能保证线程安全的代码写法?(偷偷告诉你 ...

  2. java多线程面试_Java多线程和并发基础面试问答,看过后你不会后悔

    ***:Java多线程面试问题 1:进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java ...

  3. Java多线程面试问题

    转载自  Java多线程面试问题 这篇文章主要是对多线程的面试问题进行总结的,罗列了40个多线程的问题. 1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用 ...

  4. 四、通勤路上搞定 Java 多线程面试(1)

    前言 谈到多线程,一般都会联想到高并发,但是实际上两者并不是一个概念,高并发一般指的是从业务方面的描述系统的并发负载能力,而多线程只不过是如何使CPU的利用率达到最大化.因此一般问到高并发,都会从你的 ...

  5. 史上最全Java多线程面试60题,含答案大赠送!

    [BAT必考系列!多线程60题] 多线程有什么用? 线程和进程的区别是什么? ava实现线程有哪几种方式? 启动线程方法start()和run()有什么区别? 怎么终止一个线程?如何优雅地终止线程? ...

  6. Java多线程面试准备:聊聊Executor框架

    点击上方"好好学java",选择"置顶公众号" 优秀学习资源.干货第一时间送达! 精彩内容 java实战练习项目教程 2018微服务资源springboot.s ...

  7. 40道Java多线程面试真题及答案

    这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也 ...

  8. JAVA高频面试题目集锦

    一.equals()和==,以及HashCode() =号 如果是值引用,比较值是否相等: 如果是对象引用,比较对象内存地址是否相同 equals()方法中,默认使用等号,如果说我们想要判断对象是否相 ...

  9. java多线程面试_面试之JAVA多线程

    1如何创建线程 创建多线程实现类MyThread extends Thread,继承Thread后重载run()方法,在调用类中创建对象后调用start()方法执行该线程. 创建实现类MyThread ...

  10. Java多可立,java多线程面试

    1.什么是线程和进程? 线程:线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中. 进程:进程是程序执行时的一个实例,是系统进行资源分配的基本单位. 2.什么是线程安全和线程不安全? 线程安 ...

最新文章

  1. php学习_第6章_PHP的语言结构
  2. 将让企业获利的5个人工智能趋势
  3. 吞吐量达到瓶颈后下降_如何找到 Kafka 集群的吞吐量极限?
  4. Django手写登录装饰器
  5. 【GoWeb开发实战】Cookie
  6. Mongoose aggregate 多表关联查询
  7. 【ES6(2015)】Iterator
  8. Mybatis-Plus 多表联查分页
  9. 杭电ACM--2004成绩转换
  10. ctf 改变图片高度_通过CRC32爆破修改图片的宽高 ctf-misc图片隐写
  11. linux 下root 口令破解(二) ——说一下grub的密码和安全模式
  12. [导入][转载]5行代码实现无缝滚动
  13. 【转】Java杂谈(九)--Struts
  14. java加密 js解密_【Java】JavaScript 加密 Java 解密
  15. 阿里再“牵手”中国邮政 民营快递或共享资源?
  16. Succinctly 中文系列教程(三)20220109 更新
  17. 微积分英文书籍第八版 CALCULUS eight edition
  18. 数仓工具—Hive Beeline(21)
  19. java socket解决半包、粘包问题
  20. 如何确保程序的稳定性 - Android

热门文章

  1. kubernetes视频教程笔记 (17)-Job和CronJob
  2. hutool-all 导入Excel 文件 学习笔记
  3. python超市管理系统总汇总功能解说_AdminModules --- 管理模块
  4. 注册网站域名多少钱_浅析网站域名申请注册的四种常见方式
  5. 百度题库西安交大程序C语言,程序设计基础试题(西安交大).doc
  6. linux nfs async,Linux下NFS共享以及oracle rman挂载优化
  7. Hibernate中一二级缓存使用详解
  8. 使用wsimport构建WebService客户端
  9. linux dd后无法启动盘,dd后新盘系统无法启动,解决(上)
  10. 小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_19、SpringBoot个性化启动banner设置debug日志...