提起来面试,可能被问的最多的之一,就是多线程了。比如下面的的这个招聘要求,便提到了多线程。
更有甚者,虽聊聊数语,但对于多线程这个技能的要求,甚至提升到了首位的程度,其看重程度可见一斑。
那么本次我们便来讲一个多线程常见的面试题:如何用两个线程,实现服务提供和服务消费,即一个线程用作服务提供,一个线程用作服务消费?
话不多说,直接来看示例代码:
public class ThreadTest1 {
public static volatile int amount = 0;
public static void main(String[] args) {
Thread threadProducer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("---------我要生产包子了---------");
amount = amount + 1;
System.out.println("---------包子生产完了---------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
threadProducer.start();
Thread threadConsumer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("---------我要买包子---------");
if (amount == 0) {
System.out.println("---------包子卖完了---------");
System.out.println("---------等一会儿吧---------");
} else {
System.out.println("---------包子还有---------");
amount = amount - 1;
System.out.println("---------包子买过了---------");
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
threadConsumer.start();
}
}
就以买包子为例,服务提供线程用于生产包子,包子初始数量为0,每隔1秒生产一个包子。服务消费线程用于买包子,当包子数量为0时,不做处理,等待包子生产完成;当包子数量为1时,包子数量减1,买包子成功。
程序运行效果如下:
但是,这样还是不够直观,我们想办法让买包子变成随机数量,来让两个线程“动起来”。
public class ThreadTest2 {
public static volatile int amount = 0;
public static void main(String[] args) {
Thread threadProducer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("---------我要生产包子了---------");
amount = amount + 1;
System.out.println("---------包子 + 1,现在有 " + amount + "个包子---------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
threadProducer.start();
Thread threadConsumer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
int amount_consumer = new Random().nextInt(9);
if (amount_consumer == 0) {
System.out.println("---------不好意思,我不买子---------");
} else {
System.out.println("---------我要买" + amount_consumer + "个包子---------");
if (amount_consumer > amount) {
System.out.println("---------包子不够,等一会儿吧---------");
} else {
amount = amount - amount_consumer;
System.out.println("---------包子买过了,买了" + amount_consumer + "个包子,还有 " + amount + "个包子---------");
}
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
threadConsumer.start();
}
}
同样的,服务提供线程用于生产包子,包子初始数量为0,每隔1秒生产一个包子。服务消费线程用于买包子,每次买包子的数量为随机数值。当包子数量为0或当包子数量小于本次要够买的数量时,均不做处理;当包子数量刚好大于等于本次要够买的数量时,包子数量减去本次要够买的数量,买包子成功。
来看一下运行效果:
看吧,两个线程“动起来”了吧?
至于示例代码中的 volatile 关键字,何不自己动手查一下呢?印象更深哦!感兴趣的也可以把这个关键字去掉,看这两个示例分别是什么样的运行结果。
我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!
如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!