如何在两个线程之间定义执行顺序?

时间:2018-01-12 18:10:52

标签: java multithreading synchronization

线程1打印A1 A2 A3。线程2打印B1 B2 B3。我想编写一个程序,确保两个线程运行输出时都是A1 B1 A2 B2 A3 B3。到目前为止,我已经提出了以下计划。请告诉我这是如何简化的? 我们可以使用更少的信号量吗? 可以使用wait()notify()吗?

来实现
package com.MultiThreading.threadSerialization;

import java.util.concurrent.Semaphore;

public class ThreadSerialization {

Semaphore a1Done = new Semaphore(0);
Semaphore b1Done = new Semaphore(0);
Semaphore a2Done = new Semaphore(0);
Semaphore b2Done = new Semaphore(0);
Semaphore a3Done = new Semaphore(0);

/**
 * methodA prints : A1 A2 A3
 */
public void methodA() {

    System.out.println("A1");
    a1Done.release();       
    b1Done.acquire();
    System.out.println("A2");
    a2Done.release();
    b2Done.acquire();       
    System.out.println("A3");
    a3Done.release();

}

/**
 * methodB prints : B1 B2 B3 
 */
public void methodB() {
    a1Done.acquire();
    System.out.println("B1");
    b1Done.release();
    a2Done.acquire();
    System.out.println("B2");
    b2Done.release();
    a3Done.acquire();       
    System.out.println("B3");


}

public void createTwoThreads() throws InterruptedException{ 
    ThreadSerialization ts = new ThreadSerialization();
    Thread T1 = new Thread(() -> ts.methodA());
    Thread T2 = new Thread(() -> ts.methodB());
    T1.start();
    T2.start();
    Thread.sleep(5000);
    System.out.println("test done");
}

}

2 个答案:

答案 0 :(得分:-1)

如果确保只有一个线程执行methodA而另一个线程执行methodB,则可以使用两个信号量。当您打印A1时,您可以T2打印B1的可能性。然后需要等待A2打印才能继续

  Semaphore aPrintDone = new Semaphore(0);
  Semaphore bPrintDone= new Semaphore(0);

/**
 * methodA prints : A1 A2 A3
 */
 public void methodA() {
     try {
         System.out.println("A1");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A2");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A3");
         aPrintDone.release();
    }catch (InterruptedException e1) {
         e1.printStackTrace();
    }
  }

  /**
   * methodB prints : B1 B2 B3 
  */
  public void methodB() {
    try {
        aPrintDone.acquire();
        System.out.println("B1");
        bPrintDone.release();
        aPrintDone.acquire();
        System.out.println("B2");
        bPrintDone.release();
        System.out.println("B3");
    }catch (InterruptedException e1) {
        e1.printStackTrace();
    }
}

使用wait()notify()也可以解决此问题。考虑wait()意味着线程将等待直到满足某个条件(在这种情况下是B打印,T1;以及A打印线程T2)。因此,当System.out.println完成后,它可以notify()另一个线程开始打印。我更喜欢信号量分辨率,但可以使用这些方法解决它。

答案 1 :(得分:-1)

回答wait-notify问题:是的,这是可能的。它甚至只能使用一个锁定对象。但是代码既不是非常易读也不是“安全”。代码要求methodA()methodB()之前执行,否则程序将死锁。

public class Synchronization {

    synchronized public void methodA() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A3");
        this.notify();
    }

    synchronized public void methodB() {
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B3");
    }

    public static void main(String... args) throws InterruptedException {
        Synchronization ts = new Synchronization();
        Thread t1 = new Thread(ts::methodA);
        Thread t2 = new Thread(ts::methodB);

        t1.start(); // If you switch those lines,
        t2.start(); // the program will deadlock.

        t1.join();
        t2.join();
        System.out.println("test done");
    }
}