Java并发编程(一)

本文详细解释了线程和进程的区别,多线程带来的问题,线程安全与不安全的概念,上下文切换机制,Java线程生命周期,死锁原理及预防,以及sleep和wait方法的差异。还讨论了同步和异步编程以及notify和notifyAll的区别。
摘要由CSDN通过智能技术生成

1.什么是线程和进程,区别是什么?

进程:进程指的是系统中正在运行的一个应用程序。每个进程都有自己独立的内存空间和资源,并且进程之间相互独立。

线程:线程是程序执行中的一个独立执行路径,可以独立地执行一段代码,它拥有自己的上下文信息,并能够在上下文切换中保存和恢复自己的状态。多个线程可以并发执行,实现任务的分配和处理一个进程在其执行的过程中可以产生多个线程。

区别:

  • 进程由线程组成。进程之间基本上是相互是独立的,而同一进程中的线程极有可能相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

  • 一个进程中可以有多个线程,多个线程共享进程的方法区,但是每个线程有自己的程序计数器虚拟机栈本地方法栈

线程的上下文信息包括程序计数器、寄存器、栈空间、线程状态、线程优先级等。

2.多线程可能会带来什么问题

并发编程的目的是为了能提高程序的执行效率。但是,并发编程可能会遇到很多问题,比如:内存泄漏、死锁、线程不安全等等。

3.如何理解线程安全和不安全?

线程是否安全是指多线程环境下对于同一份数据的访问是否能够保证其正确性和一致性。

  • 线程安全指的是在多线程环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。

  • 线程不安全则表示在多线程环境下,对于同一份数据,多个线程同时访问时可能会导致数据混乱、错误或者丢失。

4.什么是多线程中的上下文切换?

上下文切换是指 CPU 从一个线程转到另一个线程时,需要保存当前线程的上下文状态,恢复另一个线程的上下文状态,以便于下一次恢复执行该线程时能够正确地运行。当出现如下情况的时候,线程会从占用 CPU 状态中退出,进行上下文切换。

  • 主动让出 CPU,比如调用了 sleep()、wait() 等。

  • 时间片用完,因为操作系统要防止一个线程长时间占用 CPU 导致其他线程饿死。

  • 调用了阻塞类型的系统中断,比如请求 IO,线程被阻塞。

  • 被终止或结束运行。

  • 当线程请求进行IO操作,比如读写文件、网络通信等,由于IO操作通常需要等待外部设备的响应,线程会进入阻塞状态,同时释放CPU资源给其他线程使用。

  • 如果线程频繁进行上下文切换会降低程序执行的性能。

5.并发和并行的区别

  • 并行:可以理解为在单核 CPU 上同时运行多个程序,并发并不是真正意义上的同时进行,而是通过抢占 CPU 时间片去执行。

  • 并发:可以理解为在多个 CPU 或者一个多核 CPU 上同时运行多个程序,每个 CPU 或者多核 CPU 可以分别运行程序,二个程序互不抢占CPU资源,可以真正做到同时进行。

6.同步和异步的区别

  • 同步:发出一个调用之后,在没有得到结果之前, 该调用就不可以返回,一直等待。

  • 异步:调用在发出之后,不用等待返回结果,该调用直接返回。

回调函数是在异步编程中的重要组成,主要有以下二种应用:

  • 在事件接收方定义回调函数,并不断进行事件循环,当接收到事件产生方的事件时,会将事件作为参数传递给相应的回调函数进行处理。

  • 在事件产生方定义回调函数的规范,事件接收方定义具体的回调函数并作为参数传递给事件产生方,并在合适的时机被事件产生方调用完成对事件的处理,最后将处理结果发送给事件产生方。

7.说说Java中线程的生命周期?

Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态:

初始状态(NEW):线程被创建完成,但是还没有调用 start()。

运行状态(RUNNABLE):Java线程中将就绪和运行中两种状态笼统的称为“运行”。

  • 就绪(READY):线程对象创建后,其他线程调用了该线程对象的 start() 方法。该状态的线程位于可运行线程池中,等待被线程调度选中并分配 cpu 使用权 。

  • 运行中(RUNNING):就绪状态的线程获得了cpu 时间片,开始执行程序代码。

阻塞状态(BLOCKED):线程需要等待某个资源上锁的释放。

等待状态(WAITING):表示该线程需要等待其他线程做出通知或中断等特定动作。

超时等待状态(TIME_WAITING):相当于在等待状态的基础上增加了超时限制。当超时时间结束后,线程将会返回到 RUNNABLE 状态。

终止状态(TERMINATED):表示该线程已经运行完毕。

Java 中通过 sleep(long millis)方法或 wait(long millis)方法可以将线程置于 TIMED_WAITING 状态。

8.什么是线程死锁?如何避免死锁?

死锁:死锁是指多个线程都在等待对方释放自己所需要的资源而无法继续执行。

如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。

产生死锁的四个必要条件:

  • 互斥条件:该资源任意一个时刻只由一个线程占用。

  • 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。

  • 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。

  • 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系

如何预防死锁?

破坏死锁的产生的必要条件即可:

  • 破坏请求与保持条件:一次性申请所有的资源。

  • 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。

  • 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

9.sleep方法和wait方法对比

共同点:两者都可以暂停线程的执行。

区别:

  • sleep() 是 Thread 类的静态本地方法;wait() 则是 Object 类的本地方法。

  • sleep() 方法可以在任何地方使用;而 wait() 方法只能在同步方法或同步块中使用。

  • sleep() 方法没有释放锁;而 wait() 方法释放了锁 。

  • sleep() 通常被用于暂停执行;wait() 通常被用于线程间交互/通信。

  • sleep() 方法执行后,线程会根据指定的时间自动苏醒;wait() 方法被调用后,线程不会自动苏醒,必须等其它线程调用同一个对象上的 notify()/notifyAll() 方法来唤醒它。

  • 当一个线程调用了wait()方法进入了等待状态,它会释放某个对象的锁并暂停执行,等待其他线程通过调用相同对象上的notify()或notifyAll()方法,才会从等待队列中被移出。

  • wait(long timeout) 方法是wait()方法的另一个变体,它在等待一定时间后会自动苏醒。即使没有其他线程调用相同对象上的notify()或notifyAll()方法。

  • wait/notify等方法依赖于monitor,只有在同步代码块或者同步方法中才能调用wait、notify等方法,否则会抛出java.lang.IllegalMonitorStateException异常。

10.为什么wait方法不定义在Thread中?

wait() 是让获得对象锁的线程实现等待,会自动释放当前线程占有的对象锁。每个对象(Object)都拥有对象锁,既然要释放当前线程占有的对象锁并让其进入 WAITING 状态,自然是要操作对应的对象(Object)而非当前的线程(Thread)。

11.可以直接调用Thread类的run方法吗?

不可以,调用 start() 方法方可启动线程并使线程进入就绪状态,直接执行 run() 方法的话不会以多线程的方式执行。

new 一个 Thread,线程进入了新建状态。调用 start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 但是,直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

12.notify和notifyAll的区别

当一个线程进入wait之后,就必须等其他线程notify()/notifyAll(),才会从等待队列中被移出。使用notifyAll,可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真滴book理喻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值