java多线程交替输出_Java多线程交替打印字符

这玩意但凡有点Java基础的人,都会想到这是考察线程wait和notify,那么具体怎么做呢?如果长时间不写多线程程序,冷不丁的来一下,还真写不出。

先来复习下wait、notify的概念:wait: Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.

The current thread must own this object’s monitor.

notify: Wakes up a single thread that is waiting on this object’s monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object’s monitor by calling one of the wait methods.This method should only be called by a thread that is the owner of this object’s monitor.

notifyAll: Wakes up all threads that are waiting on this object’s monitor.

根据Javadoc的注释,可以看出wait将会让出锁,进入WAITING状态,直到其他线程调用notify(All),进入AWAKENED状态,在wait最终返回之前,需要获取锁。这意味着,AWAKENED的线程将和BLOCKING状态的线程一起竞争锁,如果竞争不过,继续待在WAITING状态。有几点需要注意:无论是wait,还是notify(All),都必须在持有锁的状态下调用

notify(All)调用后不会释放锁,而是在离开syntronized区域后

AWAKENED线程在竞争锁时没有任何优势,和BLOCKING线程优先级一样

wait的使用范式如下:synchronized (obj) {

while ()

obj.wait();

... // Perform action appropriate to condition

}

之所以使用循环条件判断,是为了防止线程过早唤醒,也就是发出notify(All)时条件谓词为真,到wait返回时,谓词不为真了。另外Javadoc指出,WAITING线程会有一定的几率自己醒来,而不是收到notify(All)的通知,虽然这极少发生。

回到最初的问题,可以启动两个线程,为他们分配一个名字name,分别为A和B,设置一个变量ticket保存着下一个可运行的线程名,只有name == ticket的线程才有权运行,这样只要改变ticket的值就可以控制线程的运行了,具体代码如下:public class Main {

public static void main(String[] args) {

new PrintChar('A').start();

new PrintChar('B').start();

}

private static class PrintChar extends Thread {

private static final Object lock = new Object();

private static char running = 'A';

private char name;

public PrintChar(char name) {

this.name = name;

}

@Override

public void run() {

for (int i = 0; i<10;i++) {

synchronized (lock) {

while (name != running) {

try {

// System.out.print(" ");

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.print(name);

loop();

lock.notify();

}

}

}

private void loop() {

if (running == 'B') {

running = 'A';

} else {

running += 1;

}

}

}

}

为了观察线程的运行等待状态,我们将注释放开,得到下面的结果,A B A

作为一个问题的延伸,考虑下面的问题:多线程打印ABCDE

小伙伴们,你想到了吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java多线程交替打印ABC的实现方式有多种。一种常见的方式是使用synchronized关键字和wait/notify方法来实现线程的阻塞和唤醒。每个线程打印完自己对应的字符后,调用notify方法唤醒下一个线程,并进入等待状态,等待下一个轮到自己打印字符。另一种方式是使用Lock和Condition来实现线程的阻塞和唤醒。每个线程打印完自己对应的字符后,调用signal方法唤醒下一个线程,并进入等待状态,等待下一个轮到自己打印字符。下面是一种使用synchronized和wait/notify方法的实现方式的示例代码: ```java public class PrintABC { private static final Object lock = new Object(); private static int count = 0; private static int maxCount = 10; public static void main(String[] args) { Thread t1 = new Thread(() -> { print("A", 0); }); Thread t2 = new Thread(() -> { print("B", 1); }); Thread t3 = new Thread(() -> { print("C", 2); }); t1.start(); t2.start(); t3.start(); } private static void print(String str, int target) { while (count < maxCount) { synchronized (lock) { while (count % 3 != target) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(str); count++; lock.notifyAll(); } } } } ``` 以上代码使用了一个lock对象作为同步锁,count变量用于记录已经打印字符数量。每个线程打印字符之前,都会先判断count是否是自己对应的值,如果不是,则调用wait方法进入等待状态,直到被唤醒后再进行判断。当一个线程打印字符后,会调用notifyAll方法唤醒其他等待线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值