《Java技术》第十次作业

时间:2021-09-27 21:32:35

(一)学习总结

1.用思维导图对java多线程的学习内容进行总结。
《Java技术》第十次作业

2.下面是一个单线程实现的龟兔赛跑游戏。

public class TortoiseHareRace {
public static void main(String[] args) {
int totalStep = 10;
int tortoiseStep = 0;
int hareStep = 0;
boolean[] flags = {true,false};
System.out.println("龟兔赛跑开始了...");
while(tortoiseStep < totalStep && hareStep < totalStep){
tortoiseStep++;
System.out.println("乌龟跑了"+tortoiseStep+"步...");
boolean isHareSleep = flags[((int)(Math.random()*10))%2];
if(isHareSleep){
System.out.println("兔子睡着了zzzz");
}else{
hareStep += 2;
System.out.println("兔子跑了"+hareStep+"步...");
}
}
}
}

阅读程序,采用实现Runnable接口的方式用多线程实现这个小游戏。下面给出主线程类,补充Tortoise线程类和Hare线程类。

补充之后的程序:

class Tortoise implements Runnable {
private int tortoiseStep = 0;
private int totalStep=10;
public Tortoise(int tortoiseStep) {
this.tortoiseStep=tortoiseStep;
}

public void run() {
while(tortoiseStep < this.totalStep) {
tortoiseStep++;
System.out.println( "乌龟跑了" + tortoiseStep + "步" );

}
}
}

class Hare implements Runnable {
private int hareStep = 0;
private int totalStep=10;
boolean[] flags = {true,false};
public Hare(int hareStep) {
this.hareStep=hareStep;
}

public void run() {

while(hareStep < this.totalStep) {
boolean isHareSleep = flags[((int)(Math.random()*10))%2];
if (isHareSleep) {
System.out.println("兔子睡着了zzzz");
} else {
hareStep += 2;
System.out.println("兔子跑了" + hareStep + "步...");
}
}
}


}

public class TortoiseHareRace {
public static void main(String[] args) {
Tortoise tortoise = new Tortoise(0);
Hare hare = new Hare(0);
System.out.println("龟兔赛跑开始了...");
Thread tortoiseThread = new Thread(tortoise);
Thread hareThread = new Thread(hare);
tortoiseThread.start();
hareThread.start();
}
}

3.下面的程序是模拟了生产者——消费者问题,生产者生产10个数,消费者依次消费10个数,运行程序,看结果是否正常?存在什么问题?说明原因。使用synchronized, wait, notify解决程序出现的问题。写出修改的部分程序即可。

class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("消费者开始消耗整数......");
// 消耗10个整数
for(int i = 1; i <= 10; i++) {
try {
// 等待随机时间
Thread.sleep((int) (Math.random() * 3000));
}
catch(InterruptedException e) {
e.printStackTrace();
}
clerk.getProduct();// 从店员处取走整数
}
}
}
class Producer implements Runnable {
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println( "生产者开始生产整数......");
// 生产1到10的整数
for(int product = 1; product <= 10; product++) {
try {
Thread.sleep((int) Math.random() * 3000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
clerk.setProduct(product); // 将产品交给店员
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Thread consumerThread = new Thread(new Consumer(clerk));
Thread producerThread = new Thread(new Producer(clerk));
consumerThread.start();
producerThread.start();
}
}
class Clerk {
private int product = -1; // -1 表示目前没有产品
// 这个方法由生产者呼叫
public void setProduct(int product) {
this.product = product;
System.out.printf("生产者设定 (%d)%n", this.product);
}
// 这个方法由消费者呼叫
public int getProduct() {
int p = this.product;
System.out.printf("消费者取走 (%d)%n", this.product);
return p;
}
}

运行结果为:

消费者开始消耗整数......
生产者开始生产整数......
生产者设定 (1)
生产者设定 (2)
生产者设定 (3)
生产者设定 (4)
生产者设定 (5)
生产者设定 (6)
生产者设定 (7)
生产者设定 (8)
生产者设定 (9)
生产者设定 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)
消费者取走 (10)

原因:没有同步、唤醒及等待

修改之后的程序:

class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("消费者开始消耗整数......");
// 消耗10个整数
for (int i = 1; i <= 10; i++) {
try {
// 等待随机时间
Thread.sleep((int) (Math.random() * 3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer implements Runnable {
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("生产者开始生产整数......");
// 生产1到10的整数
for (int product = 1; product <= 10; product++) {
try {
Thread.sleep((int) Math.random() * 3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.setProduct(product); // 将产品交给店员
}
}
}
class Clerk {
private int product = -1; // -1 表示目前没有产品
private int p ;
// 这个方法由生产者呼叫
public synchronized void setProduct(int product) {
if (this.product != -1) {
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.product = product;
p = this.product;
System.out.printf("生产者设定 (%d)%n", this.product);
getProduct();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.product = -1;
super.notify();
}
// 这个方法由消费者呼叫
public synchronized int getProduct() {
if (this.product == -1) {
try {
super.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("消费者取走 (%d)%n", p);
this.product = -1;
super.notify();
return this.product;
}
}

运行结果为:
消费者开始消耗整数......
生产者开始生产整数......
生产者设定 (1)
消费者取走 (1)
生产者设定 (2)
消费者取走 (2)
生产者设定 (3)
消费者取走 (3)
生产者设定 (4)
消费者取走 (4)
生产者设定 (5)
消费者取走 (5)
生产者设定 (6)
消费者取走 (6)
生产者设定 (7)
消费者取走 (7)
生产者设定 (8)
消费者取走 (8)
生产者设定 (9)
消费者取走 (9)
生产者设定 (10)
消费者取走 (10)

(二)实验总结

  • 1.程序设计思路:建一个runnerble接口,定义作业的份数,利用线程来发放作业,建一个测试类,创建对象,启动线程

    1. 设计思路:设计一个银行类,定义一个存储账户余额的变量以及一个存款的方法,在设计一个储户类,实现向账户存款3次,每一个储户是一个线程,最后设计一个测试类,创建客户对象,启动线程

问题:

class Person implements Runnable{
Bank b=new Bank();
private int sum=0;
public void run(){
synchronized(b){
for(int i=0;i<3;i++){
try{
Thread.sleep(300);
sum= b.add();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println( Thread.currentThread().getName()
+"正在存款,账户余额为:" + sum );
}
}
}
}

原因:不知道应该哪个为接口类

解决方案:后来查了一些资料,在银行类定义增加方法,储户为接口,调用方法,运行出来了。

(三)代码托管

  • 码云commit历史截图
    《Java技术》第十次作业