1、多线程

同步:发送一个指令需要等待返回才能发送下一条(完成一件事才能做下一件)。

异步:发送一个请求不需要等待返回,随时可以再发下一条(一次进行多个事件

线程不安全根本原因是异步,对一个资源多个线程同时操作。

1、什么是线程安全和线程不安全?

​ 压力测试或并发测试,会经常遇到此问题。

举例:假设售票系统有100张票,若线程不安全,A和B同时买了一张票后显示还有999张票,这是错的,应该只有998张票。

线程安全:

​ 安全指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结构都一样。

线程不安全:

​ 指不提供加锁机制保护,有可能会出现多个线程先后更改数据造成所得的数据是脏数据。

2、引起线程安全问题的原因:

1、线程安全问题都是有全局变量及静态变量引起的。

​ 若每个线程中全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的。

​ 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全

2、解决多线程并发访问资源安全问题的方法:

​ (1)synchronize(只给一个线程执行,完成后才到下一个线程)

​ 用来控制线程同步,保证我们的线程在多线程环境下,不被多个线程同时执行,确保数据完整性。使用方法加在方法上。

​ (2)lock

​ lock的引入让锁有了可操作性,是指我们在需要的时候手动获取锁和释放锁。

3、并发和并行有什么区别?

​ 你吃饭到一半,电话来了,你一直吃完才去接,说明你不支持并发也不支持并行

​ 你吃饭迟到一半,电话来了,你停下来接电话,接完后继续吃饭,说明你支持并发

​ 你吃饭迟到一半,电话来了,你一边打电话一半吃饭,说明你支持并行

并发有处理多个任务的能力不一定要同时进行。同一实体上多个事件。

并行同时处理多个任务的能力。不同实体上多个事件。

4、线程和进程的区别?

​ 1、进程是程序运行和资源分配的基本单位

​ 2、进程拥有独立的内存单元,而多个线程共享内存资源

​ 3、一个进程可以包含多个线程

5、守护线程是什么?

​ 守护线程(如:GC垃圾回收线程)是个服务线程,服务其他线程(如:用户线程即用户编写的线程)。

6、创建线程有哪几种方式?

​ 1、继承Thread类

继承Thread类重写run()方法。通过start()方法启动

​ 2、实现Runnable接口

​ 定义Runnable接口的实现类,重run()方法,调用start()启动线程。

​ 3、通过Callable和Future创建线程

​ Callable和Runnable很类似,主要区别在于Callable能返回运行结果能抛出异常

执行Callable方式,需要Future的实现类的支持,用于接收运算结果。FutureTask是Future接口的实现类。

public class TestCallable {

    public static void main(String[] args) {
ThreadDemo td = new ThreadDemo(); //1.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。
//参数里面放一个Callable的对象
FutureTask<Integer> result = new FutureTask<>(td); new Thread(result).start(); //2.接收线程运算后的结果
try {
Integer sum = result.get(); //FutureTask 可用于 闭锁 类似于CountDownLatch的作用,在所有的线程没有执行完成之后这里是不会执行的
System.out.println(sum);
System.out.println("------------------------------------");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
} } class ThreadDemo implements Callable<Integer> { @Override
public Integer call() throws Exception {
int sum = 0; for (int i = 0; i <= 100000; i++) {
sum += i;
} return sum;
} }

7、Runnable和Callable有什么区别?

​ 1、Runnbale接run()方法返回值void,只是去实现没有返回。

​ 2、Callable能返回结果抛出异常

8、线程有哪些状态?

​ 1、创建状态

​ 继承Thread类获实现Runnable得到线程类,new一个实例,进入初始化状态。

​ 2、就绪状态

​ 调用该对象的start()方法。该线程位于线程池中,等待被线程调度选中,获取cpu使用权。

​ 3、运行状态

​ 线程获得了cpu时间片,执行程序代码。

​ 4、阻塞状态

​ 指线程因某种原因放弃了cpu使用权,暂时停止运行。

​ 5、死亡状态

​ 线程run()、main()方法结束,或因一场退出run()方法。

9、sleep()和wait()有什么区别?

​ 1、sleep():是线程类(Thread)静态方法,让线程进入睡眠状态结束后进入就绪状态和其他线程竞争cpu执行时间。

​ 2、wait():wait()是Object类的方法。让它进入到对象相关的等待池,同时释放对象的机锁,通过notify(),notifyAll()方法唤醒等待的线程。

10、notify()和notifyAll()有什么区别?

​ 1、调用notifyAll()方法唤醒所有wait线程,notify()方法值随机唤醒一个wait线程。唤醒后进入对象锁池中竞争对象锁

​ 2、优先级高的线程竞争获得对象锁概率大没有竞争到的留在锁池,只有再次调用wait()才能进入等待池。竞争到对象锁的线程则继续往下执行,直到执行完synchronize代码块,它会释放该对象锁

11、线程run()方法和start()方法有什么区别?

​ 每个线程通过特定的run()方法完成操作,成为线程体

start()方法用来启动线程

12、创建线程池有哪几种方式?

1、newFixedThreadPool(int nThreads):固定线程池

​ 创建固定长度的线程池,每当提交一个任务就创建一个线程,知道达到线程池的最大数量,这是线程规模将不再变化,当线程发生为预期的错误而结束时,线程池会补充一个新的线程。

/**
* @author fangshixiang@vipkid.com.cn
* @description
* @date 2018-11-04 10:13
*/
public class Main { //创建一个固定线程池
private static ExecutorService executor = Executors.newFixedThreadPool(1); //向kafka里推送消费
public static void push2Kafka(Object msg) {
executor.execute(() -> {
try {
//模拟 占用的内存大小
Byte[] bytes = new Byte[1024 * 1000 * 1000];
System.out.println(Thread.currentThread().getName() + "-->任务放到线程池:" + msg);
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
} public static void main(String[] args) { //模拟高并发环境下 一直向线程池里面不停的塞任务
for (int i = 0; i < Integer.MAX_VALUE; i++) {
System.out.println("塞任务start..." + i);
push2Kafka(i);
System.out.println("塞任务end..." + i);
} }
}

2、newCachedThreadPool():缓存线程池

​ 创建一个缓存的线程池,当线程池规模超过处理需求,将自动回收空闲线程需求增加是自动添加新线程,不存在任何限制。

3、newSingleThreadExecutor():单线程执行

​ 单线程的Executor,创建单个线程执行任务,这个线程结束,会创建新的来代替它。

4、newScheduledThreadPool(intcorePoolSize)

​ 创建固定长度线程池,且延迟或定时的方式执行任务。

13、线程池包含哪些状态?

1、RUNNING:

​ 线程池一旦创建就处于这个状态,能接收新任务对已排队任务进行处理

2、SHUTDOWN:

​ 调用shutdown()方法,线程有running转变为shutdown,接收任务,但能处理已排队任务

3、STOP:

​ 调用shutdownNow()方法,线程池有(running或shutdown)转变为stop状态。不接收新任务不处理已排队任务

4、TIDYING:

​ 1、SHUTDOWN状态下,任务数为0,任务终止,线程池转变为TIDYING状态。

​ 2、SHUTDOWN状态,任务队列为空,线程池转变为TIDYING 状态

​ 3、STOP状态,任务为空

5、TERMINATED:

​ terminated状态下线程彻底终止

14、java中怎么保证多线程的运行安全?

​ 线程的安全性问题体现在:

​ 1、原子性:一个或多个操作cpu执行过程中不被中断的特性。(atomic、aynchronized、lock)

​ 2、可见性:一个线程对共享变量的修改。(synchronized、volatitle、lock)

​ 3、有序性:程序执行的顺序按照代码的先后顺序执行。(happers-before原则)

15、什么是死锁?

​ 指两个或两个以上进程竞争资源造成的一种阻塞现象。

16、怎么防止死锁?

​ 死锁的四个必要条件:

1、互斥条件进程分配到的资源不允许其他进程访问,若其他进程访问资源,只能等待,直至占有该资源的进程使用完成。

2、请求和保持条件:进程获取资源后,又对其他资源发出请求,但该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放

3、不可剥夺条件:已获得的资源,不可被剥夺

4、环路等待条件:死锁后,若干进程之间形成一种头尾相接的循环等待资源关系

只要上述条件之一不满足就不会发生死锁。

17、ThreadLocal是什么?有哪些使用场景?

​ ThreadLocal是线程本地存储,在每个线程中都创建了一个ThreadLocalMap对象,每个线程可以访问自己内部ThreadLocalMap对象内的value。能避免资源在多线程键共享

​ 使用场景:经典的场景是为每个线程分配一个 JDBC 连接 Connection。这样就能保证每个线程都在各自的 Connection 上进行数据库的操作。还有 session 管理等问题

public class TestThreadLocal {

    //线程本地存储变量
private static final ThreadLocal<Integer> THREAD_LOCAL_NUM = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
}; public static void main(String[] args) {
for (int i = 0; i <3; i++) {//启动三个线程
Thread t = new Thread() {
@Override
public void run() {
add10ByThreadLocal();
}
};
t.start();
}
} /**
* 线程本地存储变量加 5
*/
private static void add10ByThreadLocal() {
for (int i = 0; i <5; i++) {
Integer n = THREAD_LOCAL_NUM.get();
n += 1;
THREAD_LOCAL_NUM.set(n);
System.out.println(Thread.currentThread().getName() + " : ThreadLocal num=" + n);
}
} }
打印结果:启动了 3 个线程,每个线程最后都打印到 "ThreadLocal num=5",而不是 num 一直在累加直到值等于 15
Thread-0 : ThreadLocal num=1
Thread-1 : ThreadLocal num=1
Thread-0 : ThreadLocal num=2
Thread-0 : ThreadLocal num=3
Thread-1 : ThreadLocal num=2
Thread-2 : ThreadLocal num=1
Thread-0 : ThreadLocal num=4
Thread-2 : ThreadLocal num=2
Thread-1 : ThreadLocal num=3
Thread-1 : ThreadLocal num=4
Thread-2 : ThreadLocal num=3
Thread-0 : ThreadLocal num=5
Thread-2 : ThreadLocal num=4
Thread-2 : ThreadLocal num=5
Thread-1 : ThreadLocal num=5

18、说一下synchronized底层原理?

​ synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入临界区保证共享变量的内存可见性。

java中每一个对象都可以作为锁,这是synchronized实现同步的基础:

  • 普通同步方法,锁是当前实例对象
  • 静态同步方法,锁是当前类的class对象
  • 同步方法块,锁是括号里面的对象

19、synchronized和volatile的区别是什么?

​ volatile是一个很老的关键字,jdk诞生时它就有了。作用是内存可见性防止指令重排序

  • volatile本质是告诉jvm当前变量在寄存器(工作内存)中的值不确定,需要从主存中读取。synchronized是锁当前变量只有当前线程可以访问该变量
  • volatile仅能使用在变量级别,synchronized则可以使用在变量、方法和类
  • volatile实现修改可见性但不能保证原子性。而synchronized可以修改可见性和原子性。
  • volatile不会造成线程阻塞,synchronized可能会造成线程阻塞。
  • volatile标记变量不会被编译器优化,synchronized标记变量可以被编译器优化。

20、synchronized和Lock有什么区别?

​ 1、synchronized是java内置关键字,在jvm层面,lock是个java类。

​ 2、synchronized无法判断是否获取锁的状态,lock可以判断是否获取锁;

​ 3、synchronized自动释放锁,lock手动释放锁。

原文地址:https://blog.csdn.net/sufu1065/article/details/88051083

java面试:多线程的更多相关文章

  1. Java面试——多线程面试题总结

    )两者都在等待对方所持有但是双方都不释放的锁,这时便会一直阻塞形成死锁. //存放两个资源等待被使用 public class Resource { public static Object obj1 ...

  2. java面试多线程问题

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

  3. java面试——多线程

    背景:java知识比较宽泛,最好对每一类知识点进行分类总结,方便后面学习查看.该文主要用来总结多线程方面的知识点. 并发与并行的概念 并发性(concurrency)和并行性(parallel)是两个 ...

  4. Java面试:投行的15个多线程和并发面试题

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

  5. Java面试:投行的15个多线程和并发面试题(转)

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

  6. Java面试中的多线程问题

    很多核心 Java 面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线程概念时,娴熟的实际经验是必需的.这篇文章收集了 Java ...

  7. Java面试专题-多线程篇(2)- 锁和线程池

  8. Java面试专题-多线程(3)-原子操作

  9. 转:最近5年133个Java面试问题列表

    最近5年133个Java面试问题列表 Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来 ...

  10. java面试宝典(蓝桥学院)

    Java面试宝典(蓝桥学院) 回答技巧 这套面试题主要目的是帮助那些还没有java软件开发实际工作经验,而正在努力寻找java软件开发工作的学生在笔试/面试时更好地赢得好的结果.由于这套试题涉及的范围 ...

随机推荐

  1. Android使用pull解析xml格式的数据

    dom解析:基于全文加载的解析方式   sax解析:基于事件的逐行解析方式  pull解析:同sax              XmlPullParser     //解析xml文件读取短信内容    ...

  2. UITabBarController管理原则

  3. ubuntu 修改文件及文件夹的权限

    转载请注明来源:https://www.cnblogs.com/hookjc/ 打开终端进入你需要修改的目录然后执行下面这条命令chmod 777 * -R全部子目录及文件权限改为 777 来源:py ...

  4. JS快速入门(二)

    目录 JS快速入门(二) 结构图 BOM window对象 open() window子对象 location对象 history对象(了解) navigator 对象 screen对象 BOM 定时 ...

  5. 1day漏洞反推技巧实战(3)

    代码审计必备技能,github代码对比,写一笔: 搜索某开源组建漏洞,搜索出来某个版本rce: 通过消息得出:存在漏洞版本:1.10.10 ,修复漏洞版本1.10.11 去github寻找apache ...

  6. Solution -「国家集训队」「洛谷 P4451」整数的 lqp 拆分

    \(\mathcal{Description}\)   Link.   求 \[\sum_{m>0\\a_{1..m}>0\\a_1+\cdots+a_m=n}\prod_{i=1}^mf ...

  7. zabbix监控多个nginx vhost网站状态码

    需求 假设一台服务器运行了N个vhost网站,如何确定在大流量并发时候找到是哪个网站的问题呢? 这似乎是每个运维都会遇到的问题,方法有很多比如:1.看nginx日志大小确定访问量.2.通过前端代理确定 ...

  8. 轩辕展览-VR虚拟展厅设计的好处和优势是什么?

    yu情仍在继续,实体展厅很糟糕,在过去两年之中,越来越多的实体展厅因闲置而关闭,线上VR虚拟展厅设计逐渐走出圈子,凭借云展示的优势和国家政策的支持,登上展示和销售的旗帜. 产品线上展厅的优势是什么1. ...

  9. DNS中的FQDN

    FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称.(通过符号".") 例如:主机名是bigserver,域名是mycomp ...

  10. [题解]RQNOJ PID87 过河

    链接:http://www.rqnoj.cn/problem/87 思路:动态规划 定义f[i][j]表示到达第 i 块给定石头用了 j 块添加石头的最少步数. 转移方程:f[i][j]=min{f[ ...