并行和并发有什么区别?
并行指的是多个处理器同时执行不同的任务,即真正的并行执行。
并发指的是在单个处理器上看起来同时执行多个任务,实际上是通过切换任务来模拟同时执行的效果。
线程,进程和协程的区别?
进程是系统资源分配的基本单位,每个进程拥有独立的地址空间。
线程是进程内的执行单元,同一进程内的线程共享进程的资源,包括内存空间。
协程是用户空间的控制结构,不需要操作系统参与调度。协程之间的切换通常比线程切换更快。
守护线程是什么?
守护线程是在后台运行的服务线程,它的主要作用是为用户线程提供服务。当所有非守护线程结束时,不管守护线程是否还在运行,程序都会退出。
创建线程有哪几种方式?
实现
Runnable
接口。继承
Thread
类。使用
Callable
和Future
(配合ExecutorService
)。
ThreadPoolExecutor
构造函数
这个构造函数有多个重载版本,但最常用的一个包含以下参数:public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数:
corePoolSize
: 线程池的基本大小。
maximumPoolSize
: 线程池允许的最大线程数量。
keepAliveTime
: 当线程池中的线程数量大于corePoolSize
时,多余的空闲线程的存活时间。
unit
:keepAliveTime
参数的时间单位。
workQueue
: 用于存放等待执行的任务的阻塞队列。
threadFactory
: 用于创建新线程的工厂。
handler
: 当拒绝新任务时的处理程序。
说一下 runnable 和 callable 有什么区别?
Runnable
接口定义了一个run()
方法,不返回结果。Callable
接口定义了一个call()
方法,可以返回结果并通过Future
获取。
线程有哪些状态?
NEW: 新建状态。
RUNNABLE: 就绪/运行状态。
BLOCKED: 阻塞状态(等待锁)。
WAITING: 等待状态(无限期等待)。
TIMED_WAITING: 等待状态(有限期等待)。
TERMINATED: 死亡状态。
sleep()和wait() 有什么区别?
sleep()
是Thread
类的静态方法,让当前线程暂停指定的时间。wait()
是Object
类的方法,使线程进入等待状态,通常需要与synchronized
块一起使用。
notify()和 notifyAll()有什么区别?
notify()
唤醒正在等待此对象监视器的一个线程。notifyAll()
唤醒所有等待此对象监视器的线程。
线程的run()和start()有什么区别?
start()
方法启动一个新线程,并调用run()
方法。run()
方法只是简单地执行线程的任务逻辑。
创建线程池有哪几种方式?
使用
Executors
工具类提供的工厂方法。使用
ThreadPoolExecutor
手动创建。
线程池都有哪些状态?
RUNNING: 接受新任务,处理队列中的任务。
SHUTDOWN: 不接受新任务,处理队列中的任务。
STOP: 不接受新任务,不处理队列中的任务,中断正在执行的任务。
TIDYING: 所有任务都终止,工作线程退出。
TERMINATED:
terminated()
方法被调用。
线程池中submit()和execute()方法有什么区别?
execute()
提交一个Runnable任务,没有返回值。submit()
提交一个Runnable或Callable任务,返回一个Future
,可以用来获取异步计算的结果。
在java程序中怎么保证多线程的运行安全?
使用
synchronized
关键字。使用
java.util.concurrent
包中的并发工具类,如AtomicInteger
、ReentrantLock
、Semaphore
等。使用线程局部变量
ThreadLocal
。
多线程锁的升级原理是什么?
锁升级是指随着竞争情况的不同,锁可以从偏向锁升级到轻量级锁,再升级到重量级锁的过程。
升级的目的是为了减少锁带来的性能消耗。
什么是死锁?
死锁是指两个或多个线程相互等待对方持有的锁,从而无法继续执行的情况。
怎么防止死锁?
遵循良好的锁定协议,如按顺序锁定资源。
使用超时机制,避免无限期等待。
使用工具检测潜在的死锁条件。
ThreadLocal是什么?有哪些使用场景?
ThreadLocal
提供了线程本地变量,每个线程都有自己的副本,互不影响。使用场景包括事务管理、日志记录、HTTP请求等需要在线程间隔离数据的情况。
说一下synchronized底层实现原理?
synchronized
最初基于锁记录和监视器实现,使用Monitor
对象控制访问。后续版本引入了偏向锁和轻量级锁优化。
synchronized和volatile的区别是什么?
synchronized
提供原子性和可见性,可以用来同步代码块。volatile
仅提供可见性和禁止指令重排,不能保证原子性。
synchronized和Lock有什么区别?
synchronized
是内置关键字,自动释放锁。Lock
是接口,需要手动获取和释放锁。
synchronized和ReentrantLock区别是什么?
synchronized
是内置关键字,自动释放锁。ReentrantLock
是Lock
接口的实现,提供了更灵活的锁机制。
生产者消费者
在计算机科学中,“生产者-消费者”模型是一种经典的多线程编程模式,用于处理并发数据生产和消费的问题。这个模型描述了两种类型的进程或线程之间的关系:生产者负责生成数据,而消费者则负责处理这些数据。这种模式通常用于实现队列或缓冲区,以协调不同线程或进程之间的数据流。
生产者-消费者模型的关键组件
生产者:负责创建数据项,并将其放入共享数据结构(如队列或缓冲区)中。
消费者:从共享数据结构中取出数据项并处理它们。
共享数据结构:通常是一个队列或者缓冲区,用来存放生产者产生的数据,供消费者取出使用。
关键问题
同步:确保生产者不会在队列已满的情况下继续向队列中添加数据,同样确保消费者不会在队列为空的情况下尝试从中取出数据。
互斥:防止多个线程同时修改共享数据结构。
死锁:避免程序由于错误的同步而导致无法继续执行的情况发生。
解决方案
为了实现有效的生产者-消费者模型,需要考虑以下解决方案:
互斥锁:确保每次只有一个线程能够访问共享数据结构。
条件变量:用于同步生产者和消费者。当队列为空时,消费者等待;当队列满时,生产者等待。
信号量:可以用来控制多个生产者和消费者之间的访问权限,例如限制队列中的最大项目数量。