c语言父子线程交替打印,多线程交替打印ABC

对于一些需要多线程保持顺序的场景,需要我们实现线程间的交互。

常见多线程通信方式:

Synchronized + wait() + notify()

Lock + await() + signal()

semaphore

基于semaphore的变体

结合经典例题进行分析:

多线程打印10遍ABC,形如ABCABCABCABC

Synchronized + wait() + notify()

wait()与notify()作为Object类中的方法,作用如下

wait() 持有锁的线程,释放锁,一直阻塞,直到有别的线程调用notify()将其唤醒

notify() 通知一个等待线程,唤醒任意一个wait线程

private static int count = 30;

static class ThreadA extends Thread {

Thread c;

public void setC(Thread c) {

this.c = c;

}

@Override

public void run() {

while (count-- > 0) {

synchronized (c) {

synchronized (this) {

System.out.print("A");

this.notify();

}

try {

c.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

static class ThreadB extends Thread {

Thread a;

public void setA(Thread a) {

this.a = a;

}

@Override

public void run() {

while (count-- > 0) {

synchronized (a) {

synchronized (this) {

System.out.print("B");

this.notify();

}

try {

a.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

static class ThreadC extends Thread {

Thread b;

public void setB(Thread b) {

this.b = b;

}

@Override

public void run() {

while (count-- > 0) {

synchronized (b) {

synchronized (this) {

System.out.print("C");

this.notify();

}

try {

b.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

public static void main(String[] args) throws InterruptedException {

ThreadA a = new ThreadA();

ThreadB b = new ThreadB();

ThreadC c = new ThreadC();

a.setC(c);

b.setA(a);

c.setB(b);

a.start();

Thread.sleep(100);

b.start();

Thread.sleep(100);

c.start();

}

Lock + await() + signal()

await()与signal()方法有点类似wait(),notify()。不过await()与signal()是Condition工具类下的方法

Condition在内部维护了一个队列,简言之,

await()将线程包装成节点并放入队列中,阻塞当前线程

signal() 从同步队列中重新获取线程信息。

static ReentrantLock lock = new ReentrantLock();

static Condition conditionA = lock.newCondition();

static Condition conditionB = lock.newCondition();

static Condition conditionC = lock.newCondition();

static String state = "A";

static void nextState() {

switch (state) {

case "A":

state = "B";

break;

case "B":

state = "C";

break;

default:

state = "A";

}

}

static class PrintState extends Thread {

String name;

public PrintState(String name) {

this.name = name;

}

@Override

public void run() {

printState(getCurrentCondition(), getNextCondition());

}

void printState(Condition currentCondition, Condition nextCondition) {

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

lock.lock();

if (!name.equals(state)) {

try {

currentCondition.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.print(state);

nextState();

nextCondition.signal();

lock.unlock();

}

}

Condition getCurrentCondition() {

switch (name) {

case "A":

return conditionA;

case "B":

return conditionB;

default:

return conditionC;

}

}

Condition getNextCondition() {

switch (name) {

case "A":

return conditionB;

case "B":

return conditionC;

default:

return conditionA;

}

}

}

public static void main(String[] args) {

PrintState printStateA = new PrintState("A");

PrintState printStateB = new PrintState("B");

PrintState printStateC = new PrintState("C");

printStateA.start();

printStateC.start();

printStateB.start();

}

semaphore

信号量提供操作计数的方式来同步控制线程

acquire()信号量减1,若信号量为0,则阻塞

release()信号量加1

static Semaphore a = new Semaphore(1);

static Semaphore b = new Semaphore(0);

static Semaphore c = new Semaphore(0);

private static class PrintABC extends Thread {

String state;

Semaphore currentSemaphore;

Semaphore nextSemaphore;

public PrintABC(String state) {

this.state = state;

switch (state) {

case "A":

currentSemaphore = a;

nextSemaphore = b;

break;

case "B":

currentSemaphore = b;

nextSemaphore = c;

break;

default:

currentSemaphore = c;

nextSemaphore = a;

break;

}

}

@Override

public void run() {

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

try {

currentSemaphore.acquire();

System.out.print(state);

} catch (InterruptedException e) {

e.printStackTrace();

}

nextSemaphore.release();

}

}

}

public static void main(String[] args) {

PrintABC printA = new PrintABC("A");

PrintABC printB = new PrintABC("B");

PrintABC printC = new PrintABC("C");

printA.start();

printB.start();

printC.start();

}

4.基于semaphore的变体

通过上述实现方法,我们可以得知,多线程间通信的思路是由符合条件的线程获取CPU资源并执行,若不符合条件的线程获取到的CPU信息,则进行阻塞。

对于该例题,我们可以通过变量映射线程执行顺序。从而控制线程流转.

private static AtomicInteger autoInt = new AtomicInteger();

private static class PrintNum extends Thread {

private int num;

public PrintNum(int num) {

this.num = num;

}

@Override

public void run() {

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

if (autoInt.intValue() % 3 == num) {

printStr();

autoInt.intValue();

}

Thread.yield();

}

}

private void printStr() {

switch (num) {

case 0:

System.out.print("A");

case 1:

System.out.print("B");

default:

System.out.print("C");

}

}

}

public static void main(String[] args) {

PrintNum printA = new PrintNum(0);

PrintNum printB = new PrintNum(1);

PrintNum printC = new PrintNum(2);

printA.start();

printB.start();

printC.start();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值