题目1:
模拟一个人生产50个玩具,每200毫秒生产一个,当生产到第20个时加入每秒吃1个馒头,共吃完3个后在接着生产的多线程。
分析:
以下是单线程的写法,题目要求使用多线程,待改正
代码如下:
/**
* 模拟一个人生产50个玩具,每200毫秒生产一个,当生产到第20个时加入每秒
* 吃1个馒头,共吃完3个后在接着生产的多线程。
* @author Microdust
* @create 2020/11/25-9:39
*/
class People implements Runnable{
private int toy = 0;
private int bread = 3;
@Override
public void run() {
while (toy < 50){
if (toy == 20){
while (bread > 0){
eatBread();
}
}
produceToy();
}
}
public synchronized void produceToy(){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
":正在生产玩具" + (toy + 1));
toy++;
}
public synchronized void eatBread(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
":正在吃面包!");
bread--;
}
}
public class PeopleTest {
public static void main(String[] args) {
People p = new People();
Thread t = new Thread(p);
t.setName("Microdust");
t.start();
}
}
题目2:
启动两个线程对一个数字i操作
- 其中1个线程每次对i加1
- 另1个线程每次对i减1
各运行20次,结果i的值等于初始值。
分析:
1.线程同步的问题,一个线程在操作数据时另一个线程不能进入,可以想到使用synchronized或者Lock
2.第一反应肯定能想到实现两个线程,使用Integer包装类的对象作为synchronized代码块的同步监视器。
3.实践后发现,如果在main()方法中声明的Integer对象作为参数传入实现Runnable对象的构造器后,调用new Thread(Runnable r).start(),两个线程并不能共享一个同步监视器,会在run()方法体中使用各自的同步监视器,会让结果异常。
4.这里应该将数字i作为一个属性封装在另一个Number类中,并使用Number类的对象作为同步监视器,这样可以使得多个线程共用一个同步监视器。
代码如下:
/**
* 启动两个线程对一个数字i操作
* 1) 其中1个线程每次对i加1
* 2) 另1个线程每次对i减1
* 各运行20次,结果i的值等于初始值。
* @author Microdust
* @create 2020/11/25-9:59
*/
class Number{
private static int i = 0;
public Number(int i){
this.i = i;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public void add(){
i++;
}
public void sub(){
i--;
}
}
class MyThreadAdd implements Runnable {
private Number num;
public MyThreadAdd(Number num) {
this.num = num;
}
@Override
public void run() {
for (int j = 0; j < 20; j++) {
synchronized (num) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num.add();
System.out.println(Thread.currentThread().getName() +
",i = " + num.getI());
}
}
}
}
class MyThreadSub implements Runnable {
private Number num;
public MyThreadSub(Number num) {
this.num = num;
}
@Override
public void run() {
for (int j = 0; j < 20; j++) {
synchronized (num) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num.sub();
System.out.println(Thread.currentThread().getName() +
",i = " + num.getI());
}
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
Number num = new Number(0);
MyThreadAdd add = new MyThreadAdd(num);
MyThreadSub sub = new MyThreadSub(num);
Thread t1 = new Thread(add);
Thread t2 = new Thread(sub);
System.out.println("i = " + num.getI());
t1.setName("add");
t2.setName("sub");
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i = " + num.getI());
}
}
题目3:
模拟3个人排除买票,每人买1张票。售货员只有1张五元的钱,电影票5元一张,王大拿拿一张二十元的人民币排在谢大脚前面买票,谢大脚拿1张十元的人民币排在在赵四的前面买票,赵四拿1张五元的人民币排在最后。即最终的卖票次序是:谢大脚、赵四、王大拿
分析:
多线程同步问题。
代码如下:
/**
* 模拟3个人排除买票,每人买1张票。
* 售货员只有1张五元的钱,电影票5元一张,
* 王大拿拿一张二十元的人民币排在谢大脚前面买票,
* 谢大脚拿1张十元的人民币排在在赵四的前面买票,
* 赵四拿1张五元的人民币排在最后。
* 即最终的卖票次序是:谢大脚、赵四、王大拿
* @author Microdust
* @create 2020/11/25-15:09
*/
class SalesMan{
private int money = 5;
private int price = 5;
public void addMoney(){
money += price;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public boolean canBuyTicket(int money){
if (this.money >= money - price){
return true;
}else{
return false;
}
}
}
class BuyTicket implements Runnable{
private int money;
private int ticket = 0;
private SalesMan salesMan;
public BuyTicket(int money,SalesMan salesMan){
this.money = money;
this.salesMan = salesMan;
}
@Override
public void run() {
while (ticket == 0){
synchronized (salesMan){
if (salesMan.canBuyTicket(money)){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
salesMan.addMoney();
ticket++;
System.out.println(Thread.currentThread().getName()
+ ":买到一张票!");
}
}
}
}
}
public class ThreadTest2 {
public static void main(String[] args) {
SalesMan salesMan = new SalesMan();
BuyTicket b1 = new BuyTicket(20,salesMan);
BuyTicket b2 = new BuyTicket(10,salesMan);
BuyTicket b3 = new BuyTicket(5,salesMan);
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b2);
Thread t3 = new Thread(b3);
t1.setName("王大拿");
t2.setName("谢大脚");
t3.setName("赵四");
t1.start();
t2.start();
t3.start();
}
}
题目4:
编写生产者消费者多线程程序,设有一个最大库存量为4的电视机仓库,生产10台电视机,一边生产一边销售(消费)。
分析:
生产者消费者问题。
代码如下:
/**
* 编写生产者消费者多线程程序,设有一个最大库存量为4的电视机仓库,
* 生产10台电视机,一边生产一边销售(消费)。
* @author Microdust
* @create 2020/11/25-16:08
*/
class WareHouse{
private final static int MAX_COUNTS = 4;
private int nums = 0;
public synchronized boolean producerProduce(){
if (nums < MAX_COUNTS){
nums++;
System.out.println(Thread.currentThread().getName() +
":开始生产第" + nums + "个电视");
notify();
return true;
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
}
public synchronized boolean consumerConsume(){
if (nums > 0){
System.out.println(Thread.currentThread().getName() +
":开始销售第" + nums + "个电视");
nums--;
notify();
return true;
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
}
}
class Producer extends Thread{
private WareHouse wareHouse;
private int count = 0;
public Producer(WareHouse wareHouse){this.wareHouse = wareHouse;}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +
"开始生产...");
while (count != 10) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (wareHouse.producerProduce()){
count++;
};
}
}
}
class Consumer extends Thread{
private WareHouse wareHouse;
private int count = 0;
public Consumer(WareHouse wareHouse){this.wareHouse = wareHouse;}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +
"开始消费...");
while (count != 10) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (wareHouse.consumerConsume()){
count++;
};
}
}
}
public class ProductorTest {
public static void main(String[] args) {
WareHouse wareHouse = new WareHouse();
Producer p1 = new Producer(wareHouse);
Consumer c1 = new Consumer(wareHouse);
p1.setName("生产者1");
c1.setName("消费者1");
p1.start();
c1.start();
}
}