Java面试题(六)多线程经典编程题
经典的多线程编程题
- 猜数字游戏
- 键盘输入练习
- 3个线程轮流打印ABC
- 多窗口买票
猜数字游戏
题目说明:有2个线程,第一个线程A随机一个100内的数,第2个线程B来猜,B每次猜一个数后A会判断,如果猜对了程序结束,如果猜大了,或者猜小了,就要缩小猜的范围继续猜;
例如:
A线程随机一个数:66
B线程第一次猜44
A线程说猜小了,继续猜
B线程此时猜的范围就是44-100以内
然后B线程继续猜88
A线程说猜大了,继续猜
B线程此时才的范围就是44-88
然后同上继续,直到最后猜中为止
//先准备一个实体类
public static class Guess{
//1=猜大了,2=猜小了,3=猜对了
private Integer isBigOrSmall = 3;
//猜的数
private Integer guessNum;
//随机数
private Integer randomNum;
//每次猜数的边界值
private Integer max = 100;
private Integer min = 1;
//get set
}
public static void main(String[] args) {
Guess guess = new Guess();
//A线程随机一个1-100内的数
Integer randomNum = (int)(Math.random() * guess.getMax()) + guess.getMin();
guess.setRandomNum(randomNum);
System.out.println("随机给你一个数1-100的数,看你能猜出来吗?" + randomNum);
Random random = new Random();
//B线程第一次随机猜的一个数1-100
Integer guessNum = random.nextInt(guess.getMax())+guess.getMin();
guess.setGuessNum(guessNum);
Thread t1 = new Thread(){
@Override
public void run(){
int count = 1;
while (true){
if(guess.getIsBigOrSmall() == 1){
Integer guessNum = (int)(Math.random() * (guess.getGuessNum() - guess.getMin())) + guess.getMin();
guess.setGuessNum(guessNum);
}else if(guess.getIsBigOrSmall() == 2){
Integer guessNum = (int)(Math.random() * (guess.getMax() - guess.getGuessNum())) + guess.getGuessNum();
guess.setGuessNum(guessNum);
}
System.out.println("我第" + count + "次猜这个数是:" + guess.getGuessNum() + "---猜的范围是" + guess.getMin() + "-" + guess.getMax());
count ++;
try {
sleep(2001);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread(){
@Override
public void run(){
while (true){
if(guess.getGuessNum() != null){
if(guess.getGuessNum() > randomNum){
System.out.println("你猜大了");
guess.setIsBigOrSmall(1);
guess.setMax(guess.getGuessNum());
}else if(guess.getGuessNum() < randomNum){
System.out.println("你猜小了");
guess.setIsBigOrSmall(2);
guess.setMin(guess.getGuessNum());
}else{
System.out.println("恭喜你,猜对了!");
guess.setIsBigOrSmall(3);
System.exit(0);
}
try {
sleep(2010);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t1.start();
t2.start();
}
键盘输入练习
线程A每次在控制台给出a-z任意字符,然后在控制台输入对应的字符,B线程判断是否输入正确,正确就得分+1,错误得分-1;注意只有在控制台输入后,B线程才能判断,等B判断完之后A线程才能给出字符
//准备一个答案类
public static class Answer{
//题目给出的字符
private char subject;
//当前得分
private int score = 0;
//get set
}
public static void main(String[] args) {
System.out.println("键盘输入练习(输入#结束程序)");
System.out.println("输入显示的字母(回车)\n");
char startChar = 'a',endChar = 'z';
Answer answer = new Answer();
//从a开始输入
answer.setSubject(startChar);
Thread t1 = new Thread(){
@Override
public void run() {
char c = startChar;
while (true){
System.out.println("显示的字符:" + c);
LockSupport.park();
c = (char) (c + 1);
if(c > endChar){
c = endChar;
}
answer.setSubject(c);
}
}
};
Scanner sc = new Scanner(System.in);
Thread t2 = new Thread(){
@Override
public void run() {
while (true){
char c = sc.next().charAt(0);
if(answer.getSubject() == c){
answer.setScore(answer.getScore() + 1);
System.out.println("输入对了,目前分数:" + answer.getScore());
}else{
answer.setScore(answer.getScore() - 1);
System.out.println("输入错了,目前分数:" + answer.getScore());
}
LockSupport.unpark(t1);
if(c == '#'){
System.out.println("答题结束:最终得分:" + answer.getScore());
System.exit(0);
}
}
}
};
t1.start();
t2.start();
}
3个线程轮流打印ABC
3个线程轮流打印ABC,可以通过锁来实现
public class ThreadDemo {
//锁
private static Lock lock = new ReentrantLock();
//根据余数判断该哪个线程打印了
private static int remainder = 0;
//第一个线程
static class ThreadFirst extends Thread{
@Override
public void run(){
for(int i=0;i<10;) {
lock.lock();
try {
while(remainder % 3 == 0) {
System.out.println("线程1拿到锁:A");
remainder++;
i++;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
//第二个线程
static class ThreadSecond extends Thread{
@Override
public void run(){
for(int i=0;i<10;) {
lock.lock();
try {
while(remainder % 3 == 1) {
System.out.println("线程2拿到锁:B");
remainder++;
i++;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
//第三个线程
static class ThreadThird extends Thread{
@Override
public void run(){
for(int i=0;i<10;) {
lock.lock();
try {
while(remainder % 3 == 2) {
System.out.println("线程3拿到锁:C");
remainder++;
i++;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) {
new ThreadFirst().start();
new ThreadSecond().start();
new ThreadThird().start();
}
}
多窗口买票
例如ABC3个线程卖100张票,卖完为止
public class SellTicket {
static class Window implements Runnable{
private static int ticket = 100;
@Override
public void run() {
while (true){
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this){
if (ticket <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票");
ticket--;
}
}
}
}
public static void main(String[] args) {
Window w = new Window();
Thread w1 = new Thread(w,"窗口1");
Thread w2 = new Thread(w,"窗口2");
Thread w3 = new Thread(w,"窗口3");
w1.start();
w2.start();
w3.start();
}
}