如何强制我的线程按顺序运行?

时间:2018-05-12 01:43:35

标签: java multithreading

我正在尝试使用线程打印字母表。我收到了字母印刷但我无法以正确的顺序获得它们。

所以我得到的东西有B,A,D,C

有没有办法强制执行顺序?我希望线程1然后等待,然后线程2等,然后再循环

这就是我所拥有的:

public class Letters {
    public static void main(String[] args) {
        char[] arr1 = new char[]{'A', 'E', 'I', 'M', 'Q', 'U', 'Y'};
        char[] arr2 = new char[]{'B', 'F', 'J', 'N', 'R', 'V', 'Z'};
        char[] arr3 = new char[]{'C', 'G', 'K', 'O', 'S', 'W'};
        char[] arr4 = new char[]{'D', 'H', 'L', 'P', 'T', 'X'};

        mythread c1 = new mythread(arr1);
        mythread c2 = new mythread(arr2);
        mythread c3 = new mythread(arr3);
        mythread c4 = new mythread(arr4);

        Thread t1 = new Thread (c1);
        Thread t2 = new Thread (c2);
        Thread t3 = new Thread (c3);
        Thread t4 = new Thread (c4);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
}

static class mythread extends Thread{
    char arr []; //= {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    mythread () {};

    mythread (char [] x) {
        this.arr = x; // .arrcopy didn't work
    }

    public void run () {
        try {
            printletters(arr);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized void printletters(char [] arr) throws InterruptedException {
        int q = 0;

        for(int count = 0 ; count < arr.length; count++) {
            System.out.println(arr[count]);
            wait(10);
            q++;
            if(q >= 4) {
                notifyAll();
                q = 0;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

要提供除评论中已有的内容之外的其他内容,这是确保线程按顺序运行并将演示创建自定义同步器的一种方法的基本方法。同步器是一种控制线程之间执行的方法。

有很多方法可以解决这个问题。为简单起见,将使用4个同步对象。每个线程将“阻塞”它的前任线程,打印一个字母,并在完成'信号'后继续线程。阻塞和信令由同步器实现。

这是同步器:

public class TSync {

private final Lock lock = new ReentrantLock();
private final Condition previousThreadDone = lock.newCondition();
private boolean ready = false;  // Guarded by lock

public void waitForPreviousThread() throws InterruptedException {
    lock.lock();
    try {
        while (!ready)
            previousThreadDone.await();
        ready = false;
    } finally {
        lock.unlock();
    }
}

public void signalNextThread() {
    lock.lock();
    try {
        ready = true;
        previousThreadDone.signal();
    } finally {
        lock.unlock();
    }
}

}

现在你的Letters类现在使用TSync类来协调执行流程:

public class Letters {
public static void main(String[] args) {

    char[] arr1 = new char[] { 'A', 'E', 'I', 'M', 'Q', 'U', 'Y' };
    char[] arr2 = new char[] { 'B', 'F', 'J', 'N', 'R', 'V', 'Z' };
    char[] arr3 = new char[] { 'C', 'G', 'K', 'O', 'S', 'W' };
    char[] arr4 = new char[] { 'D', 'H', 'L', 'P', 'T', 'X' };

    TSync sync1 = new TSync();
    TSync sync2 = new TSync();
    TSync sync3 = new TSync();
    TSync sync4 = new TSync();

    Mythread c1 = new Mythread(arr1, sync1, sync2);
    Mythread c2 = new Mythread(arr2, sync2, sync3);
    Mythread c3 = new Mythread(arr3, sync3, sync4);
    Mythread c4 = new Mythread(arr4, sync4, sync1);

    Thread t1 = new Thread(c1);
    Thread t2 = new Thread(c2);
    Thread t3 = new Thread(c3);
    Thread t4 = new Thread(c4);

    t1.start();
    t2.start();
    t3.start();
    t4.start();

    System.out.println("Signalling Thread 1 is ready to work");
    sync1.signalNextThread();

}
}

class Mythread extends Thread {
private final char[] arr;
private final TSync waitOnSync;
private final TSync signalSync;

public Mythread(char[] arr, TSync waitOnSync, TSync signalSync) {
    super();
    this.arr = arr;
    this.waitOnSync = waitOnSync;
    this.signalSync = signalSync;
}

@Override
public void run() {
    boolean isInterrupted = false;
    for (int i=0; i<arr.length && !isInterrupted; i++) {
        try {
            waitOnSync.waitForPreviousThread();
            System.out.println(arr[i]);
            signalSync.signalNextThread();
        } catch (InterruptedException e) {
            isInterrupted = true;
        }
    }
}
}

现在字母表将按顺序打印(即同步器确保每个线程按您希望的顺序运行)。