一、作业要求:
1、用两个线程玩猜数字游戏,第一个线程负责随机给出1-100之间的一个整数,
第二个线程负责猜出这个数。
2、要求每当第二个线程给出自己的猜测之后, 第一个线程都会提示“猜小了”、“猜大了”或“猜对了”。
3、猜数之前,要求第二个线程要等到第一个线程设置好要猜的数。
4、第一个线程设置好猜测数之后,两个线程还要互相等待,其原则是,第二个线程给出自己的猜测后,等待第一个线程给出的提示; 第一个线程给出提示后,等待第二个线程给出猜测,如此进行,直到第二个线程给出正确的出猜测后, 两个线程进入死亡状态。
二、思路:
- 线程一的作用
- 给出随机数random
- 判断猜测数字guessnumber与random大小关系,并给出判断
- 线程二的作用
- 猜测数字
- 为了实现线程一与线程二之间的联系,采用线程通信的方式。(wait和notify)
三、代码
import java.util.Scanner;
/*
* 4、用两个线程玩猜数字游戏,第一个线程负责随机给出1-100之间的一个整数,
* 第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测之后,
* 第一个线程都会提示“猜小了”、“猜大了”或“猜对了”。猜数之前,
* 要求第二个线程要等到第一个线程设置好要猜的数。第一个线程设置好猜测数之后,
* 两个线程还要互相等待,其原则是,第二个线程给出自己的猜测后,等待第一个线程给出的提示;
* 第一个线程给出提示后,等待第二个线程给出猜测,如此进行,直到第二个线程给出正确的出猜测后,
* 两个线程进入死亡状态。
*/
//线程1:给1-100的随机数 判断
//线程2:猜
public class GuessNumber {
public static void main(String[] args) {
Num n = new Num();
GuessThread guess = new GuessThread(n);
JudgeThread judge = new JudgeThread(n);
judge.start();
guess.start();
}
}
// Num类完成线程之间的同步
class Num {
int number;// 保存猜测的数
boolean first = true;
boolean stop = false;
}
class GuessThread extends Thread {
Num num;
public GuessThread(Num num) {
this.num = num;
}
@Override
public void run() {
Scanner sc = new Scanner(System.in);
while (true) {
try {
synchronized (num) {
if (num.first) {// 如果是第一次执行
num.wait();
} else if (num.stop) {
System.out.println("猜数结束");
return;
} else {
System.out.println("请输入猜测的数(1-100):");
int guess = sc.nextInt();
// 猜数结束就需要等待,判断线程
num.number = guess;
num.notify();
num.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//判断线程
class JudgeThread extends Thread {
Num num;
public JudgeThread(Num num) {
this.num = num;
}
@Override
public void run() {
int random = 0;
while (true) {
try {
synchronized (num) {
if (num.first) {
random = (int) (Math.random() * 100 + 1);
System.out.println("随机数已产生:" + random);
num.first = false;
num.notify();
num.wait();
} else {
// 判断过程
if (num.number < random) {
System.out.println("猜小了!");
} else if (num.number > random) {
System.out.println("猜大了!");
} else {
System.out.println("猜对了!");
num.stop = true;
num.notify();// 猜对结束之前
return;
}
num.notify();
num.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
以上是人为去输入猜测的数字,下面是自动猜数的一些代码。
//自动猜数字:利用线程通信完成
public class GuessNumber2 {
public static void main(String[] args) {
Num2 num2 = new Num2();
GuessNum gn = new GuessNum(num2);
JudgeNum jn = new JudgeNum(num2);
jn.start();
gn.start();
}
}
class Num2 {
int number;
int flag = 0;// 用于比较猜测数字的大小:1:猜数大 0:猜对 -1:猜数小
boolean first = true;// 判断是否是第一次猜数
boolean stop = false;// 判断是否猜对
}
class GuessNum extends Thread {
Num2 num2;
String name = "GuessNumber-->";
public GuessNum(Num2 num2) {
this.num2 = num2;
}
@Override
public void run() {
// Scanner sc = new Scanner(System.in);
int max = 100;
int min = 1;
int guess = (int) (Math.random() * (max - min + 1) + 1);
while (true) {// 在判断正确以前需要循环
try {
synchronized (num2) {
if (num2.first) {
num2.wait();
} else if (num2.stop) {
System.out.println("---猜数结束---");
return;
} else {
// System.out.println("请输入猜测的数(1-100):");
// int guess = sc.nextInt();
// 猜数结束就需要等待,判断线程
switch (num2.flag) {// 根据flag的判断,逐渐缩小范围
case 0:// flag为0
break;
case 1:// 猜数大
if (max > guess)
max = guess;// 最大值用前一次的guess替代
guess = (int) (Math.random() * (max - min + 1) + min);
break;
case -1:
if (min < guess)
min = guess;// 最小值用前一次的guess替代
guess = (int) (Math.random() * (max - min + 1) + min);
break;
}
num2.number = guess;
Thread.sleep(1000);// 暂停1秒
System.out.println();
System.out.println(name + guess);
System.out.println("max=" + max + " min=" + min);
num2.notify();
num2.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class JudgeNum extends Thread {
Num2 num2;
String name;
public JudgeNum(Num2 num2) {
this.num2 = num2;
this.name = "JudgeNumber-->";
}
@Override
public void run() {
int random = 0;
while (true) {// 在判断正确以前需要循环
try {
synchronized (num2) {// 同步
if (num2.first) {// 当first为true
random = (int) (Math.random() * 100 + 1);
System.out.println(name + "随机数已产生:" + random);// 产生随机数
num2.first = false;
num2.notify();// 先唤醒
num2.wait();// 再等待
} else {
Thread.sleep(1000);
switch (judge(random)) {
case 1:
System.out.println(name + "猜大了!");
num2.flag = 1;
break;
case -1:
System.out.println(name + "猜小了!");
num2.flag = -1;
break;
case 0:
System.out.println(name + "猜对了!");
num2.flag = 0;
num2.stop = true;// 把stop设置成true
num2.notify();
return;
}
num2.notify();
num2.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
int judge(int jnum) {
int result = 0;
if (num2.number > jnum) {
result = 1;
} else if (num2.number < jnum) {
result = -1;
}
return result;
}
}
四、总结
- 多线程的相关内容不是很难,但是需要根据不同的情况去设置线程就相对比较复杂了。