1、进程与线程的概念
进程是指一段正在运行的程序,是资源管理的最小单位,在进程中可以有若干个线程
线程是指程序执行过程中能够执行程序代码的一个执行单元,是程序执行的最小单元
2、进程间的通信方式
管道、信号、消息队列、共享内存、内存映射、信号量、套接字(Socket)
其中信号和信号量是主要用于触发,而不是用于传递数据
3、并行与并发的概念
并行指的是在同一时刻同时运行的程序
并发指的是在同一时间间隔内运行的程序
4、线程的五种状态及其之间的转换
线程拥有五种状态,分别是新建状态、就绪状态、运行状态、阻塞状态、结束状态
新建状态:在一个程序刚被创建时,就处于新建状态,处于新建状态的线程可以通过start()方法进入就绪状态;
就绪状态:在一个线程创建后调用start()方法后,该线程便进入了就绪状态,就绪是指该线程已获得除了CPU执行权以外的所有资源,处于就绪状态的线程等待系统调度获得CPU执行权,便进入运行状态
运行状态:就绪状态的线程得到CPU的执行权后处于的状态,该状态的线程会执行线程的任务,并且该线程可以进入就绪状态、阻塞状态和结束状态。
当系统分配给该线程的时间片结束后,也就是失去CPU的执行权,该线程会进入就绪状态;
当该线程执行阻塞式I/O时,会释放CPU的执行权,进入阻塞状态;
当线程想要获取被其它线程已获得的锁时,会进入阻塞状态;
当线程调用了sleep()方法后,会进入阻塞状态;
线程的任务正常执行完后进入结束状态;
阻塞状态:处于运行状态的线程想要获得某个锁但被其它线程已占用,或者线程正在执行阻塞式I/O等,便会进入阻塞状态。并且处于该状态的线程只有当引起阻塞的条件不成立后,才会进入就绪状态
结束状态:线程任务执行完,进入结束状态;或者线程被停止;或者线程抛出异常
5、单线程、多线程的理解
单线程下只能一一执行,某个后续线程想要执行必须等待前一个线程结束才能执行
多线程下线程之间可以并行运行,处于执行中的线程在等待资源不再使用CPU时,可以让其它线程执行
虽然多线程会增大内存的使用,并且不会提高程序的执行速度,但是可以减少程序的整体运行时间
6、实现多线程有哪些方法?
三种
继承Thread类,重写run()方法,启动时调用start()方法。Thread类本质上也是实现了Runnable接口
实现Runnable接口,实现接口中的run()方法。启动时创建Thread对象,初始化参数为实现Runnable接口的类的对象,调用start()方法启动
实现Callable接口,实现接口中call()方法。Callable接口与Runnable类似,但是可以得到线程执行后的返回值。启动需要线程池调用submit()方法。
推荐使用哪种实现多线程?
在实现多线程时,推荐使用实现Runnable接口的方法,
从Java语言来说,Java是单继承,多实现的,为了方便以后代码的可扩展性,继承和实现两种方式推荐使用实现。
7、产生死锁的必要条件及如何避免死锁
死锁是指多个线程之间因为想要获取其它线程获得的资源,并且自身不释放获得的资源导致线程之间互相等待而造成的一种现象。
产生死锁有四个必要条件:
互斥:一个资源只能有一个线程获得
请求与保持:在请求其它资源的同时,不释放已获得的资源
不可剥夺:线程已获得的资源不能被其它线程抢用
循环等待:多个线程之间形成环形等待资源的状态
当将上述四个条件破坏掉任意一个时,就不会产生死锁。但是互斥不可避免,所以只能考虑其它三个:
线程必须一次性的获得运行所需要的资源;
在线程获得部分资源后,尝试获得其它资源获取不到时,应该释放其已获得的资源;
资源的获取是有顺序要求的;
8、sleep()、wait()的区别
sleep()是Thread类中的静态方法,执行该方法会使得当前线程睡眠一段指定时间,并且线程不会释放获得的锁对象
wait()是Object类的方法,可以用于线程间的通信,并且必须获得锁对象才能执行该方法,,必须在同步方法或同步代码块中使用,会释放锁对象,
两个都使得线程从执行状态进入阻塞状态