一、简述线程、进程、程序的基本概念?
1.进程: 我们把运行中的程序叫做进程,每个进程都会占用内存与CPU资源,进程与进程之间互相独立.
2.线程: 线程就是进程中的一个执行单元,负责当前进程中程序的执行。一个进程可以包含多个线程。多线程可以提高程序的并行运行效率。
3.程序:是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
二、创建线程的几种方法
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
三、线程有什么优缺点?
优点:
1. 在多核CPU中,通过并行计算提高程序性能. 比如一个方法的执行比较耗时,现在把这个方法逻辑拆分,分为若干个线程并发执行,提高程序效率。
2. 可以解决网络等待、io响应导致的耗时问题。
3. 提高CPU的使用率.提高网络资源的利用率
缺点:
1. 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
2. 线程之间对共享资源的访问会造成资源安全问题;
3. 多线程存在上下文切换问题CPU 通过时间片分配算法来循环执行任务,所以本身就会占用cpu资源
四、start 和 run 方法有什么区别?
调用start方法方可启动线程,而run方法只是thread类中的一个普通方法调用,还是在主线程里执行。
五、可以直接调用Thread类的run()方法吗
可以直接调用,但是只是执行了一个普通的run方法而已,并没有真正的启动线程
六、Thread类的 sleep 方法和对象的 wait 方法都可以让线程暂停执行,它们有什么区别?
1、方法归属不同
sleep()方法是属于Thread类中的,而wait()方法,则是属于Object类中的。
2、sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,当指定的时间到了又会自动恢复运行状态。
所以在调用sleep()方法的过程中,线程不会释放对象锁。
3、调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,
只有针对此对象调用notify()方法后该线程才准备获取对象锁进入运行状态。
七、notify 和 notifyAll 有什么区别?
notify方法只能唤醒一个线程,notifyall可以唤醒所有线程,通常与wait()方法搭配使用。
七、sleep、join、yield 方法有什么区别?
1.sleep是暂停当前线程,把cpu的给其他线程使用
2.join是当前线程等待指定的线程执行完成。
如果线程A执行了线程B的join()方法,并且线程B还没有执行完成,线程A将会被阻塞,直到线程B执行完成。
3.yield
thread.yield() 让CPU的时间片,尽量切换其他线程去执行,但不会释放它持有的锁
八、线程的生命周期(状态)
1.新建状态
2.就绪状态
3.阻塞状态
4.等待状态
5.死亡状态
九、Java关键字volatile作用
1、保证变量的可见性
当一个变量被声明为volatile时,它的值会被存储在主内存中,而不是线程的本地内存中。
每次读取该变量时,都会从主内存中读取最新的值
2、防止指令重排序
在多线程并发下,线程之间是通过主内存来共享数据的,
当一个线程修改了某个变量的值时,这个新值会被写入该线程的本地内存,并不会立即写入主内存。
如果没有使用volatile关键字来修饰该变量,其他线程可能无法及时看到这个变量的最新值,从而导致并发问题。
十、为什么代码会重排序?
提高效率
为了提高程序的执行效率,编译器和CPU都可能会对程序进行指令重排序。
指令重排序是指在不改变程序执行结果的前提下,重新安排指令的执行顺序,以提高程序的执行效率。
十一、Java关键字synchronized作用以及原理?
1.Java关键字synchronized是用于实现多线程同步的机制,确保多个线程在访问共享资源时不会产生竞争和冲突,从而避免数据不一致的情况。
其主要原理是基于Java对象的内部锁,即监视器锁(Monitor Lock),确保在同一时刻只有一个线程可以访问被保护的代码块或方法。
2.当一个线程尝试获取被synchronized关键字保护的资源时,
如果该资源已被其他线程占用,该线程就会进入等待状态。
当占用资源的线程释放该资源时,等待队列中的线程会竞争获取该资源,
并且只有一个线程会成功获取到该资源,其他线程继续等待。
3.synchronized关键字保证了可见性和原子性,可见性是通过JVM底层的内存屏障来实现的,原子性则是通过监视器锁的互斥性来实现的。
在synchronized块内,线程获得了锁,它将会清空工作内存,从而使得该线程使用的变量能够从主内存中重新读取,同时也会把工作内存中的变量写回到主内存中。
这样,其他线程就可以读取到最新的值,从而保证了可见性。
十二、请你描述一下怎么使用lock锁的?
Lock lock = new ReentrantLock();
try{
lock.lock();
//可能会出现线程安全的操作
}finally{
//尽量在finally中释放锁
lock.unlock();
}
十三、Lock和synchronized区别
1.语法层面:
1.1.synchronized是关键字,源码在jvm中,用c++ 语言实现
1.2.Lock 是接口,源码由jdk 提供,用java语言实现
1.3.使用 synchronized 时,退出同步代码块锁会由jvm自动释放,而使用Lock时,需要手动调用unlock方法释放锁
,否则可能会导致死锁等问题
2.功能层面
相同点:
2.1都可以用来控制多个线程访问共享资源的互斥性。
2.2都支持可重入锁机制,即同一个线程在已经获得锁的情况下能够再次获取该锁。
2.3都支持在发生异常或者代码执行完毕时自动释放锁资源,避免死锁等问题。
不同点:
2.4 Lock 提供了更多的锁机制选择,例如公平锁、非公平锁、可重入锁、读写锁等多种类型;而 synchronized 只有一种类型,即独占锁(排他锁)。
2.5 Lock 应该优先考虑在高并发场景下使用,可以获得更好的性能和灵活性;而 synchronized 关键字则更适合用于简单的线程同步场景,易于使用和维护
十四、线程池的优点
1. 避免创建线程和销毁线程的性能开销
2. 提高响应速度
3. 线程池的线程可以重复使用
十五、什么是死锁?
死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。
十六、线程池的执行流程