一、多线程相关知识点回顾
什么是进程
程序是指令和数据的有序集合,是一个静态概念,其本身没有任何运行的意义。进程是程序在处理机上的一次执行过程,是一个动态的概念。进程是一个具有一定独立功能的程序。进程是一个实体,每一个进程都有自己的地址空间。
进程的状态
进程执行时的间断性决定了进程具有多种状态。事实上,运行中的进程具有三种状态。
- 就绪状态
- 运行状态
-
阻塞状态
什么是线程
线程是进程的组成部分。一个进程可以有多个线程,一个线程必须有一个父进程。线程是处理器调度的基础单位。
线程实现的两种方式
线程的状态
二、生产者和消费者的案例分析
- 假设饭店里有一个厨师和一个服务员,服务员必须等到厨师准备好膳食后,才能上菜。每当厨师准备好膳食后,才会通知服务员。这是一个任务协作的示例,厨师代表生产者,服务员代表消费者。生产者不断生产产品,消费者不断消费产品,这构成了多线程开发中的一个经典案例----生产者与消费者。
- 实质是要解决多个线程共享一个数据时,如何处理线程安全问题。java的多线程是使用抢占式来实现的,这里我们要使用对象锁来保证线程安全。
- 部分代码如下
public void set(String name,String desc){
synchronized (this) { //在对象上上锁
if(flag==false){ //表示不能生产,所以就让出 CPU,并释放对象锁
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//表示正在生产
this.name = name;
try {
//模拟生产食物的时间过程
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.desc = desc;
flag = false;
this.notify(); //唤醒在此对象锁上的任意一个线程
}
}
public void get(){
synchronized (this) {
if(flag==true){ //表示不能消费
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//正在消费
System.out.println(this.name + "--" + this.desc);
flag = true;
this.notify(); //唤醒在此对象锁上的任意一个线程
}
}
具体代码可参考
https://github.com/JacksonMike/Java_ultimate/blob/master/ProducerConsumerDemo.java
- 在这个案例中,我们需要达到的效果是:两个线程在各自调用food对象的方法的时候,要限制两个方法以互斥的方式进行,比如例如A线程调用food的set方法,那么B线程只能等到A线程完成set方法后才能调用。具体应用场景可以引申为: 一个是负责提供数据的线程,把数据拿到后放到对列,另一个不断的从队列中取出数据进行消费。
三、多进程的经典面试题
- 生产这消费者模型的作用是什么?
- sleep方法和wait方法有什么区别?
- 如何在两个线程之间共享数据?
- 为什么wait()方法和notify()要在同步块中调用?
- wait()方法和notify()方法在放弃对象监视器时有什么区别?
- Thread.sleep(0)的作用是什么?