栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程交替打印ABC

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程交替打印ABC

对于一些需要多线程保持顺序的场景,需要我们实现线程间的交互。
常见多线程通信方式:

  • Synchronized + wait() + notify()
  • Lock + await() + signal()
  • semaphore
  • 基于semaphore的变体

结合经典例题进行分析:

多线程打印10遍ABC,形如ABCABCABCABC
  1. 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();
    }
  1. 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();
    }
  1. 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();
    }
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号