Java多线程刷题

进程和线程的区别是什么?

答:进程是资源分配的最小单位,线程时执行任务的最小单元,进程之间的资源以及通信不是共享的,线程之间的有些资源是共享的。

答案:进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。
线程与进程的区别归纳:
a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
c.调度和切换:线程上下文切换比进程上下文切换要快得多。
d.在多线程OS中,进程不是一个可执行的实体。

整理:进程是资源分配的基本单位,线程时cpu调度的基本单位
线程间对于进程的资源是共享的,一个进程可以包括多个线程

创建线程有几种不同的方式?你喜欢哪一种?为什么

答:创建线程有三种方式:(1)实现Runnable接口,重写run方法 (2)实现Callable接口,重写call方法 (3)继承Thread类,重写run方法
我最喜欢的方式是实现Callable方式,因为这种方式可以抛出异常,而且call方法是有返回值的,方便信息的传递

答案:有4种方式可以用来创建线程:
继承Thread类
实现Runnable接口
应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。
还有一种方式是实现Callable接口

整理:创建线程有四种方式:(1)实现Runnable接口,重写run方法 (2)实现Callable接口,重写call方法 (3)继承Thread类,重写run方法 (4)通过线程池创建线程
我最喜欢的方式是实现Callable方式,因为这种方式可以抛出异常,而且call方法是有返回值的,方便信息的传递,当要创建多个线程的时候,更喜欢用线程池,这样不但高效,而且方便管理。

概括的解释下线程的几种可用状态

答:线程可用状态有:start,running,阻塞状态,
Start状态是指线程已经准备就绪,调用start方法就可以运行了
Running是指线程正在执行任务
阻塞状态是指线程被中断,就会处于此状态

答案:1. 新建( new ):新创建了一个线程对象。
2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。
3. 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。
4. 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种:
(一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。
(二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。
(三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。 当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。
5. 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

同步方法和同步代码块的区别是什么

同步方法是对整个方法加锁,同步监视器是方法的调用者
同步代码块是对代码块加锁,同步监视器是括号中传入的对象

答案:区别:
同步方法默认用this或者当前类class对象作为锁;
同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;
同步方法使用关键字 synchronized修饰方法,而同步代码块主要是修饰需要进行同步的代码,用 synchronized(object){代码内容}进行修饰;

整理:同步方法是用synchronize修饰的方法,如果该方法是普通方法,则同步监视器是调用该方法的对象,如果该方法是静态方法,同步监视器是类。同步方法是对整个方法加锁以保证安全性。
同步代码块是synchronize(){},同步监视器是圆括号中传入的对象,同步代码块是对整个代码块加锁,相比较同步方法锁粒度更细。

在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步

同步监视器会调用lock操作

答案:监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。

什么是死锁

死锁是两个线程或多个线程相互等待对方释放资源时发生的僵持状态,代码不会出现任何的提示,可以调用jvm的调试工具来检查错误。

答案:所谓死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:
互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求

如何确保N个线程可以访问N个资源同时又不导致死锁?

答案:使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

猜你喜欢

转载自blog.csdn.net/weixin_42220532/article/details/89971604