文章目录
一、生产者消费者模型是什么?
其实生产者消费者模型就是线程之间的通信,因为听名字就知道这个模型肯定有两个人,一个是生产者,一个是消费者,生产者一边生产,消费者一边消费。这两个线程同时进行,并且是对同一个物体进行操作,所以涉及到这两个线程的通信。
二、代码
- 以一个例子来写代码,比如一个家里有一个母亲往家里挣钱,然后儿子和女儿花家里的钱,母亲边挣,两个败家孩子边花。
- 代码如下
public class MyConusm {
public static void main(String[] args) {
Home home = new Home();
Mother mother = new Mother(home);
Son son = new Son(home);
Daughter daughter = new Daughter(home);
mother.start();
son.setName("儿子");
daughter.setName("女儿");
son.start();
daughter.start();
}
}
//家是共享数据,也是锁,就要等妈妈挣完钱,儿子女儿才能花,
class Home{
private int money = 0;
//这里要加锁的原因是当money++的时候,儿子可能就花了,明明挣钱之后money是10,但打印出来可能是9.
public synchronized void MakeMoney() {
if( money < 20 ) {
money++;
System.out.println("妈妈开始挣钱" + money);
//notifyAll()的意思是只要妈妈挣了一块钱,就释放其他两个线程,儿子女儿就可以花了
notifyAll();
}else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//这里同理
public synchronized void LayOut() {
if( money > 0 ) {
money--;
System.out.println(Thread.currentThread().getName() + "开始花钱 " + money);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
notifyAll();
}else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Mother extends Thread{
Home home;
public Mother(Home home) {
this.home = home;
}
public void run() {
while(true) {
home.MakeMoney();
}
}
}
class Son extends Thread{
Home home;
public Son(Home home) {
this.home = home;
}
public void run() {
while(true) {
home.LayOut();
}
}
}
class Daughter extends Thread{
Home home ;
public Daughter(Home home) {
this.home = home;
}
public void run() {
while(true) {
home.LayOut();;
}
}
}
三、常见面试题
说说 sleep() 方法和 wait() 方法区别和共同点
区别:
- sleep()只是休眠 ,wait()则是释放锁,只有释放了锁,其他线程才能进来
- sleep()执行完里面的时间之后会自动释放锁,wait() 需要notify() 和notifyAll()
- sleep() 主要用于线程的暂停,wait() 用于线程的通信
相同点:两者都可以暂停线程的执行。
为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法
这涉及到线程的生命周期:
- 首先,我们通过new 来创建一个线程,
- 然后这个线程去cpu哪里排队,等cpu给他时间片(start())
- 然后执行run()方法
- 执行完run()方法之后(或者调用stop())线程结束,当然这里可能会有线程的阻塞什么的,就比如sleep(),wait(),但这些在这个问题里不是重点
- 以上才是线程的执行过程
- 要是直接调用run()方法,他就只是调用了run()方法,是按顺序执行的,达不到主程序和线程里的程序同时执行的效果。
一个线程两次调用start()方法会出现什么情况
Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误。
在上个题里面简单说了下线程的生命周期,当一个线程启动时,它可能处于不同的等待状态,再次start()是必然会报错的。