帮人做网站被徐州派出所抓百度竞价排名费用
进程和线程
进程即程序的一次执行过程,各个进程之间是独立的。线程是更小的单位,一次进程中,可能会有多个线程,可能会相互影响,各个线程有自己的程序计数器,虚拟机栈和本地方法栈,同时共同使用堆和方法区资源
线程的生命周期和状态
NEW:线程被创建出来,但是未调用start()方法
RUNNABLE:线程调用了start()方法
BLOCKED:等待锁释放
WAITING:线程调用Object.wait()、Thread.join()或LockSupport.park()方法时,进入等待状态
TIME_WAITING:线程调用Thread.sleep()、Object.wait()或Thread.join()方法时,带有超时时间参数,进入计时等待状态。
TERMINATED:当线程执行完它的任务或发生异常时,它进入终止状态。
线程上下文切换
线程执行过程时有自己的运行状态(称作上下文),如程序计数器等信息,退出cpu状态,加载另一个cpu的上下文。
发生切换时机
主动让出cpu,调用sleep()或wait()方法
时间片用完
被终止或结束运行
死锁
什么是死锁
多个线程同时阻塞,互相等待对象释放资源
死锁产生条件
互斥条件:同一个资源在同一时刻只能被一个线程占有
不可剥夺条件:一个线程持有资源时,不能被其他线程剥夺
请求与保持条件:一个线程因请求资源阻塞时,会继续占用已有的资源
循环等待条件:若干线程形成首尾相接的循环等待关系
如果避免死锁
破坏不可剥夺条件:线程可以剥夺其他线程占用的资源
破坏请求与保持条件:一次性申请所有资源
破坏循环等待条件:按序申请资源,反序释放资源
wait和sleep方法
sleep()方法不会释放对象锁。当一个线程调用sleep()方法时,它会让当前线程休眠一段时间,但是它并不会释放对象锁。其他线程仍然无法获取该对象的锁。
wait()方法会释放对象锁。当一个线程调用wait()方法时,它会让当前线程等待,并释放对象锁,以便其他线程可以获取该对象的锁并执行。
sleep是Thread类的方法,而wait是Objec类的方法.
代码示例
public static void main(String[] args) {final Object lock = new Object();Thread waitingThread = new Thread(() -> {synchronized (lock) {System.out.println(LocalTime.now() + " " + Thread.currentThread().getName() + " Waiting thread is running");try {lock.wait(); // 线程等待,释放对象锁} catch (InterruptedException e) {e.printStackTrace();}System.out.println(LocalTime.now() + " " + Thread.currentThread().getName() + " Waiting thread is done");}});Thread notifyingThread = new Thread(() -> {synchronized (lock) {try {Thread.sleep(1000); //休眠1s} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(LocalTime.now() + " " + Thread.currentThread().getName() + " Notifying thread is running");lock.notify(); // 唤醒等待中的线程System.out.println(LocalTime.now() + " " + Thread.currentThread().getName() + " Notifying thread is done");}});waitingThread.start();notifyingThread.start();}
输出结果
15:36:44.350 Thread-0 Waiting thread is running
15:36:45.352 Thread-1 Notifying thread is running
15:36:45.352 Thread-1 Notifying thread is done
15:36:45.352 Thread-0 Waiting thread is done
Synchronized
原理
每个对象都有一个与之关联的监视器(monitor),当一个线程进入一个对象的 synchronized
方法或代码块时,它会尝试获取这个对象的内置锁。如果这个锁已经被其他线程获取了,那么当前线程将被阻塞,直到获取到这个锁为止。
当一个线程获取到对象的内置锁后,它就可以执行 synchronized
方法或代码块中的操作。在执行完这些操作后,线程会释放对象的内置锁,这样其他线程就有机会获取到这个锁,
ReentrantLock
原理
ReentrantLock 是通过 lock() 和 unlock() 方法来实现锁的获取和释放,支持可重入特性和公平性选择,同时还提供了条件变量的支持。其底层实现是基于 AQS 框架的,通过这些机制来实现多线程的同步和互斥操作。
Synchronized和ReentrantLock比较
相同点:可重入,
区别:synchronized依赖JVM,而ReetranLock依赖API;
ReentrantLock实现等待可中断,公平锁,选择通知