HTML可以做彩票网站吗,投资网站,wordpress oss ftp,美食网页模板免费下载文章目录 Java并发基础并行和并发有什么区别#xff1f;说说什么是进程和线程#xff1f;Java线程创建方式#xff1f;Runnable和Callable接口的区别#xff1f;为什么调用start()方法时会执行run()方法#xff0c;不直接调用run()方法#xff1f;sleep()和wait()的区别说说什么是进程和线程Java线程创建方式Runnable和Callable接口的区别为什么调用start()方法时会执行run()方法不直接调用run()方法sleep()和wait()的区别线程的生命周期(状态)什么是守护线程线程间通信有哪些通信方式volatile和synchronized关键字 ThreadLocal是什么你在项目中用到过ThreadLocal吗ThreadLocal原理要答出这几个点ThreadLocalMap怎么解决Hash冲突的父子线程怎么共享数据 Java内存模型说一下你对Java内存模型JMM的理解 线程池什么是线程池线程池主要参数有哪些 锁synchronized用过吗怎么使用说说synchronized和ReentrantLock的区别CAS是什么如何解决ABA问题如何解决ABA问题 Java并发基础
并行和并发有什么区别
从操作系统的角度来看线程是CPU分配的最小单位。
并行就是同一时刻两个线程都在执行。即两个CPU去分别执行两个线程。
并发就是同一个时刻只有一个执行但是一个时间段内两个都执行了并发依赖于CPU的切换因为切换时间段用户无感知。
说说什么是进程和线程
要说线程必须得先说进程
进程进程是代码在数据集合上的一次运行活动是系统进行资源分配和调度的基本单位。线程线程是进程的一个执行路径一个进程中至少有一个线程进程中的多个线程共享进程的资源。
Java线程创建方式
继承Thread类、实现Runnable接口、实现Callable接口线程池
Runnable和Callable接口的区别
Runnable里面的run()方法没有返回值只能处理一些简单的任务无法抛出异常
实现Callable接口重写call()方法这种方式可以通过FutureTask获取任务执行的返回值,可以处理一些复杂的线程任务可以抛出异常。
为什么调用start()方法时会执行run()方法不直接调用run()方法
JVM执行start方法会先创建一条线程由创建出来的新线程去执行thread的run方法这才起到多线程的效果。
**为什么我们不能直接调用run()方法**也很清楚 如果直接调用Thread的run()方法那么run方法还是运行在主线程中相当于顺序执行就起不到多线程的效果。
**为什么我们不能直接调用run()方法**也很清楚 如果直接调用Thread的run()方法那么run方法还是运行在主线程中相当于顺序执行就起不到多线程的效果。
sleep()和wait()的区别 sleep方法属于Thread类的静态方法而wait方法属于Object类的实例方法。因此sleep方法可以直接通过Thread类调用而wait方法需要通过对象实例调用。 sleep方法会让当前线程暂停执行指定的时间然后继续执行。在睡眠期间线程不会释放锁。wait方法会让当前线程暂停执行并释放对象的锁使得其他线程可以访问该对象。 sleep方法不需要被唤醒一旦时间到达线程会自动恢复执行。wait方法需要被其他线程调用notify或notifyAll方法来唤醒。 sleep方法使用的是线程的本地资源不会释放对象的锁。wait方法会释放对象的锁使得其他线程可以获取该对象的锁。 sleep方法适用于线程暂停执行一段时间后继续执行的场景而wait方法适用于线程等待某个条件满足后再继续执行的场景。
线程的生命周期(状态)
new(新建)、runnable(可运行)、blocked(阻塞)、waiting(等待)、time waiting(超时等待)和terminated(终止)。 什么是守护线程
Java中的线程分为两类分别是daemon线程(守护线程)和user(用户)线程。
在JVM 启动时会调用 main 函数main函数所在的线程就是一个用户线程。其实在 JVM 内部同时还启动了很多守护线程 比如垃圾回收线程。
那么守护线程和用户线程有什么区别呢区别之一是当最后一个非守护线程束时 JVM会正常退出而不管当前是否存在守护线程也就是说守护线程是否结束并不影响 JVM退出。换而言之只要有一个用户线程还没结束正常情况下JVM就不会退出。
线程间通信有哪些通信方式 volatile和synchronized关键字
关键字volatile可以用来修饰字段成员变量就是告知程序任何对该变量的访问均需要从共享内存中获取而对它的改变必须同步刷新回共享内存它能保证所有线程对变量访问的可见性。
关键字synchronized可以修饰方法或者以同步块的形式来进行使用它主要确保多个线程在同一个时刻只能有一个线程处于方法或者同步块中它保证了线程对变量访问的可见性和排他性。
等待/通知机制
可以通过Java内置的等待/通知机制wait()/notify()实现一个线程修改一个对象的值而另一个线程感知到了变化然后进行相应的操作。
管道输入/输出流
管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于它主要用于线程之间的数据传输而传输的媒介为内存。
管道输入/输出流主要包括了如下4种具体实现PipedOutputStream、PipedInputStream、 PipedReader和PipedWriter前两种面向字节而后两种面向字符。
使用Thread.join()
如果一个线程A执行了thread.join()语句其含义是当前线程A等待thread线程终止之后才从thread.join()返回。。线程Thread除了提供join()方法之外还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。
使用ThreadLocal
ThreadLocal即线程变量是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
可以通过set(T)方法来设置一个值在当前线程下再通过get()方法获取到原先设置的值。
ThreadLocal是什么
ThreadLocal是线程本地变量如果你创建了一个ThreadLocal变量那么访问这个变量的每个线程都会有这个变量的一个本地拷贝多个线程操作这个变量的时候实际是操作自己本地内存里面的变量从而起到线程隔离的作用避免了线程安全问题。
创建
//创建一个ThreadLocal变量
public static ThreadLocalString localVariable new ThreadLocal();写入
线程可以在任何地方使用localVariable,写入变量。
localVariable.set(张三”);读取
线程在任何地方读取的都是它写入的变量。localVariable.get();你在项目中用到过ThreadLocal吗
有用到过的用来做用户信息上下文的存储。
登录后用户每次访问接口都会在请求头携带一个token在控制层可以根据这个token解析用户基本信息但是在业务层也需要用到用户信息(id)可以用到ThreadLocal在控制层拦截请求把用户信息存入ThreadLocal这样我们在任何一个地方都可以取出ThreadLocal中存的用户数据。
ThreadLocal原理要答出这几个点
Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals每个线程都有一个属于自己的ThreadLocalMap。ThreadLocalMap内部维护着Entry数组每个Entry代表一个完整的对象key是ThreadLocal的弱引用value是ThreadLocal的泛型值。每个线程在往ThreadLocal里设置值的时候都是往自己的ThreadLocalMap里存读也是以某个ThreadLocal作为引用在自己的map里找对应的key从而实现了线程隔离。ThreadLocal本身不存储值它只是作为一个key来让线程往ThreadLocalMap里存取值。
ThreadLocalMap怎么解决Hash冲突的
我们可能都知道HashMap使用了链表来解决冲突也就是所谓的链地址法。
ThreadLocalMap没有使用链表自然也不是用链地址法来解决冲突了它用的是另外一种方式——开放定址法。开放定址法是什么意思呢简单来说就是这个坑被人占了那就接着去找空着的坑。
父子线程怎么共享数据
这时候可以用到另外一个类——InheritableThreadLocal
public class InheritableThreadLocalTest {public static void main(String[] args) {final ThreadLocal threadLocal new InheritableThreadLocal();// 主线程threadLocal.set(不擅技术);//子线程Thread t new Thread() {Overridepublic void run() {super.run();System.out.println(张三 threadLocal.get());}};t.start();}
}Java内存模型
说一下你对Java内存模型JMM的理解
Java内存模型Java Memory ModelJMM是一种抽象的模型被定义出来屏蔽各种硬件和操作系统的内存访问差异。
线程池
什么是线程池
说的简单点就是帮我们管理线程的池子。
避免增加创建线程和销毁线程的资源损耗。因为线程其实也是一个对象创建一个对象需要经过类加载过程销毁一个对象需要走GC垃圾回收流程都是需要资源开销的。
提高响应速度。 如果任务到达了相对于从线程池拿线程重新去创建一条线程执行速度肯定慢很多。
重复利用。 线程用完再放回池子可以达到重复利用的效果节省资源
线程池主要参数有哪些
线程池有七大参数需要重点关注corePoolSize、maximumPoolSize、workQueue、handler这四个。
corePoolSize
此值是用来初始化线程池中核心线程数当线程池中线程池数 corePoolSize时系统默认是添加一个任务才创建一个线程池。当线程数 corePoolSize时新任务会追加到workQueue中。
maximumPoolSize
maximumPoolSize表示允许的最大线程数 (非核心线程数核心线程数)当BlockingQueue也满了但线程池中总线程数 maximumPoolSize时候就会再次创建新的线程。
keepAliveTime
非核心线程 (maximumPoolSize - corePoolSize ) ,非核心线程闲置下来不干活最多存活时间。
unit
线程池中非核心线程保持存活的时间的单位
TimeUnit.DAYS; 天TimeUnit.HOURS; 小时TimeUnit.MINUTES; 分钟TimeUnit.SECONDS; 秒TimeUnit.MILLISECONDS; 毫秒TimeUnit.MICROSECONDS; 微秒TimeUnit.NANOSECONDS; 纳秒
workQueue
线程池等待队列维护着等待执行的Runnable对象。当运行当线程数 corePoolSize时新的任务会被添加到workQueue中如果workQueue也满了则尝试用非核心线程执行任务等待队列应该尽量用有界的。
threadFactory
创建一个新线程时使用的工厂可以用来设定线程名、是否为daemon线程等等。
handler
corePoolSize、workQueue、maximumPoolSize都不可用的时候执行的饱和策略。
锁
synchronized用过吗怎么使用
synchronized经常用的用来保证代码的原子性。它可以用来修饰方法或代码块确保在同一时间只有一个线程可以执行被synchronized修饰的代码。
synchronized主要有三种用法
修饰实例方法: 作用于当前对象实例加锁进入同步代码前要获得 当前对象实例的锁
synchronized void method() {//业务代码
}修饰静态方法也就是给当前类加锁会作⽤于类的所有对象实例 进⼊同步代码前要获得当前 class 的锁。因为静态成员不属于任何⼀个实例对象是类成员 static 表明这是该类的⼀个静态资源不管 new 了多少个对象只有⼀份。 如果⼀个线程 A 调⽤⼀个实例对象的⾮静态 synchronized ⽅法⽽线程 B 需要调⽤这个实例对象所属类的静态 synchronized ⽅法是允许的不会发⽣互斥现象因为访问静态 synchronized ⽅法占⽤的锁是当前类的锁⽽访问⾮静态 synchronized ⽅法占⽤的锁是当前实例对象锁。
synchronized void staic method() {//业务代码
}修饰代码块 指定加锁对象对给定对象/类加锁。 synchronized(this|object) 表示进⼊同步代码库前要获得给定对象的锁。 synchronized(类.class) 表示进⼊同步代码前要获得 当前 class 的锁
说说synchronized和ReentrantLock的区别
synchronized是Java语言的关键字而ReentrantLock是基于JDK的API层面进行的实现
ReentrantLock提供了一种能够中断等待锁的线程的机制通过lock.lockInterruptibly()来实现这个机制ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。synchronized与wait()和notify()/notifyAll()方法结合实现等待/通知机制ReentrantLock类借助Condition接口与newCondition()方法实现。ReentrantLock需要手工声明来加锁和释放锁一般跟finally配合释放锁。而synchronized不用手动释放锁。
区别synchronizedReentrantLock锁实现机制对象头监视器模式依赖AQS灵活性不灵活支持响应中断、超时、尝试获取锁释放锁形式自动释放锁显式调用unlocak()支持锁类型非公平锁公平锁非公平锁条件队列单条件队列多个条件队列可重入支持支持支持
CAS是什么
Compare and Swap是一种基于锁的操作乐观锁的一种实现方式。它用于在多线程环境下保证数据的一致性和并发性。
CAS操作包含三个操作数内存地址(或变量)、旧的预期值、新的预期值
执行过程
读取内存地址中的当前值和旧的值比较如果当前两个值相等将新的值写入内存地址完成操作如果当前值不等于旧的预期值则说明其他线程已经修改了该内存地址的值操作失败。
CAS操作的特点是乐观锁它并不直接对数据进行锁定而是通过比较和交换的方式来实现数据的一致性。
如何解决ABA问题
CASCompare and Swap操作中可能会遇到ABA问题这是指一个值被另一个线程修改后又改回原来的值CAS操作无法判断这个值是否被其他线程修改过。
解决方法 1.使用带版本号的CAS操作每次修改数据同时修改版本号在CAS操作时同时检查版本号是否一致都一致再进行交换操作
2.使用带标记的CAS操作在CAS操作是还需要比较替换标记。每次进行修改操作时都会改变标记的值。如果值恢复原来的值但是标记也会发生变化。
据进行锁定而是通过比较和交换的方式来实现数据的一致性。
如何解决ABA问题
CASCompare and Swap操作中可能会遇到ABA问题这是指一个值被另一个线程修改后又改回原来的值CAS操作无法判断这个值是否被其他线程修改过。
解决方法 1.使用带版本号的CAS操作每次修改数据同时修改版本号在CAS操作时同时检查版本号是否一致都一致再进行交换操作
2.使用带标记的CAS操作在CAS操作是还需要比较替换标记。每次进行修改操作时都会改变标记的值。如果值恢复原来的值但是标记也会发生变化。