更新时间:2020-11-16 17:29:01 来源:极悦 浏览1202次
多线程系列一直是Java面试题中的经典,多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术,是我们学习Java技术的必学课程之一。本文我们就根据以往的资料和前辈们的面试经验来总结一下必看多线程面试题。
1. 线程和进程的区别?
·性质不同
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
·适用范围不同
使用进程目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。
线程为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。
2.设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.
package com.wang.reflect;
/**
* 设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.
* @author Administrator
*
*/
public class Demo02 {
private int i=0;
public static void main(String[] args) {
Demo02 demo=new Demo02();
Add add = demo.new Add();
Sub sub = demo.new Sub();
for(int i=1;i<=2;i++){
new Thread(add,"线程"+i).start();
new Thread(sub,"线程"+i).start();
}
}
//定义一个内部类Add,实现功能每次对i加一
class Add implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
addOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//定义一个内部类Sub,实现功能每次对i减1
class Sub implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
subOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void addOne() {
i++;
System.out.println(Thread.currentThread().getName()+"加一的值为:"+i);
}
public synchronized void subOne(){
i--;
System.out.println(Thread.currentThread().getName()+"减一的值为:"+i);
}
}
3.volatile关键字的作用
一个非常重要的问题,是每个学习、应用多线程的Java程序员都必须掌握的。理解volatile关键字的作用的前提是要理解Java内存模型,这里就不讲Java内存模型了,可以参见第31点,volatile关键字的作用主要有两个:
(1)多线程主要围绕可见性和原子性两个特性而展开,使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据
(2)代码底层执行不像我们看到的高级语言—-Java程序这么简单,它的执行是Java代码–>字节码–>根据字节码执行对应的C/C++代码–>C/C++代码被编译成汇编语言–>和硬件电路交互,现实中,为了获取更好的性能JVM可能会对指令进行重排序,多线程下可能会出现一些意想不到的问题。使用volatile则会对禁止语义重排序,当然这也一定程度上降低了代码执行效率
从实践角度而言,volatile的一个重要作用就是和CAS结合,保证了原子性,详细的可以参见java.util.concurrent.atomic包下的类,比如AtomicInteger。
4. 创建线程有哪几种方式?
创建线程有三种方式:
·继承 Thread 重写 run 方法;
·实现 Runnable 接口;
·实现 Callable 接口。
5. 线程有哪些状态?
线程的状态:
·NEW 尚未启动
·RUNNABLE 正在执行中
·BLOCKED 阻塞的(被同步锁或者IO锁阻塞)
·WAITING 永久等待状态
·TIMED_WAITING 等待指定的时间重新被唤醒的状态
·TERMINATED 执行完成
6. sleep() 和 wait() 有什么区别?
·类的不同:sleep() 来自 Thread,wait() 来自 Object。
·释放锁:sleep() 不释放锁;wait() 释放锁。
·用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。
7. 在 Java 程序中怎么保证多线程的运行安全?
方法一:使用安全类,比如 Java. util. concurrent 下的类。
方法二:使用自动锁 synchronized。
方法三:使用手动锁 Lock。
手动锁 Java 示例代码如下:
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println("获得锁");
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println("释放锁");
lock. unlock();
}
8. synchronized 和 volatile 的区别是什么?
·volatile 是变量修饰符;synchronized 是修饰类、方法、代码段。
·volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性。
·volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
9. 为什么要使用多线程
·使用线程可以把占据时间长的程序中的任务放到后台去处理。
·用户界面更加吸引人,这样比如用户点击了一个按钮去触发某件事件的处理,可以弹出一个
·进度条来显示处理的进度。
·程序的运行效率可能会提高。
·在一些等待的任务实现上如用户输入,文件读取和网络收发数据等,线程就比较有用了。
10、如何在两个线程之间共享数据
通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待,比方说阻塞队列BlockingQueue就是为线程之间共享数据而设计的。
多线程作为目前的主流Java技术之一,一直以来备受关注,也是我们参加各大公司的必考知识点之一。有了上面的10道必看的多线程面试题,小伙伴们可以以此为基础拓展自己的多线程知识,全面温习多线程的各个知识点,全面学习更多的java面试题,在面试中争取突破自我,取得最好的成绩!
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习