按顺序java运行3个线程

时间:2012-10-20 14:26:22

标签: java multithreading notify

我有3个帖子 第一次印刷A. 第二次印刷B. 第三次印刷C

我想按顺序打印A B C A B C A B C等......

所以我写了下面的程序,但我无法实现同样的目标。 我知道当status = 1时,例如B1和C1线程正在等待,当我执行notifyAll()时,两个等待线程都被唤醒,并且根据CPU分配,它可能会打印B或C.

在这种情况下,我只希望在A之后打印B.

我需要做哪些修改。

public class NotifyAllExample {

    int status=1;
    public static void main(String[] args) {

        NotifyAllExample notifyAllExample = new NotifyAllExample();

        A1 a=new A1(notifyAllExample);
        B1 b=new B1(notifyAllExample);
        C1 c=new C1(notifyAllExample);

        a.start();
        b.start();
        c.start();
    }
}

class A1 extends Thread{
    NotifyAllExample notifyAllExample;

    A1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

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

                    if(notifyAllExample.status!=1){
                        notifyAllExample.wait();
                    }

                    System.out.print("A ");
                    notifyAllExample.status = 2;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 1 :"+e.getMessage());
        }

    }

}

class B1 extends Thread{

    NotifyAllExample notifyAllExample;

    B1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

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

                    if(notifyAllExample.status!=2){
                        notifyAllExample.wait();
                    }

                    System.out.print("B ");
                    notifyAllExample.status = 3;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 2 :"+e.getMessage());
        }

    }
}


class C1 extends Thread{

    NotifyAllExample notifyAllExample;

    C1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

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

                    if(notifyAllExample.status!=3){
                        notifyAllExample.wait();
                    }

                    System.out.print("C ");
                    notifyAllExample.status = 1;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 3 :"+e.getMessage());
        }

    }
}

10 个答案:

答案 0 :(得分:8)

将这些IF语句转换为WHILE语句以获得所需的行为:

if (notifyAllExample.status != 2){
    notifyAllExample.wait();
}

while (notifyAllExample.status != 2){
    notifyAllExample.wait();
}

这将确保如果一个线程被通知,它将不会退出while循环,直到状态值达到预期值。

另外,将status标记为volatile,以便线程不会有本地副本。

答案 1 :(得分:7)

 public class RunThreadsInOrder implements Runnable {

    static int numThread = 1;
    static int threadAllowedToRun = 1;
    int myThreadID;
    private static Object myLock = new Object();

    public RunThreadsInOrder() {
        this.myThreadID = numThread++;
        System.out.println("Thread ID:" + myThreadID);
    }

    @Override
    public void run() {
        synchronized (myLock) {
            while (myThreadID != threadAllowedToRun) {
                try {
                    myLock.wait();
                } catch (InterruptedException e) {

                } catch (Exception e) {}
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }

            System.out.println("myThreadID is running: " + myThreadID);
            myLock.notifyAll();
            threadAllowedToRun++;
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Thread t1 = new Thread(new RunThreadsInOrder());
        Thread t2 = new Thread(new RunThreadsInOrder());
        Thread t3 = new Thread(new RunThreadsInOrder());
        Thread t4 = new Thread(new RunThreadsInOrder());
        Thread t5 = new Thread(new RunThreadsInOrder());
        Thread t6 = new Thread(new RunThreadsInOrder());
        Thread t7 = new Thread(new RunThreadsInOrder());

        t7.start();
        t6.start();
        t5.start();
        t4.start();
        t3.start();
        t2.start();
        t1.start();

    }
}

答案 2 :(得分:1)

我被要求在一次访谈中写一个类似的程序,其中添加的条件是它应该是可扩展的,我们可以提供自己的线程数,并且他们应该打印字符,第一个线程打印'A'然后后续线程打印B,C,D等。我就是这样做的。

public class AlternateCharPrinter {

    public static char ch = 65;

    private static void createAndStartThreads(int count) {
        Object lock = new Object();
        for (int i = 0; i < count; i++) {
            new Thread(new AlternateCharRunner((char) (65 + i), lock)).start();
        }

    }

    public static void main(String[] args) {
        createAndStartThreads(4);
    }

}

class AlternateCharRunner implements Runnable {

    private char ch;
    private Object lock;
    private static int runnerCount;

    public AlternateCharRunner(char ch, Object lock) {
        this.ch = ch;
        this.lock = lock;
        runnerCount++;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (lock) {
                while (ch != AlternateCharPrinter.ch) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(AlternateCharPrinter.ch++);
                if (AlternateCharPrinter.ch == (65 + runnerCount)) {
                    AlternateCharPrinter.ch = 65;
                }
                lock.notifyAll();
            }
        }
    }

}

答案 3 :(得分:0)

您需要替换

if (notifyAllExample.status!=1)

while (notifyAllExample.status!=1)

和其他2个类一样。如果没有,那么一旦等待退出线程继续而不知道它是否轮到它。

答案 4 :(得分:0)

替换:

if(notifyAllExample.status!=1){
   notifyAllExample.wait();
}

使用:

while(notifyAllExample.status!=1){
   notifyAllExample.wait();
}

所有班级都相应。

答案 5 :(得分:0)

    public class Main {
        public static void main(String[] args) throws IOException{
        Thread t1 = new Thread(new A(), "1");
        Thread t2 = new Thread(new A(), "2");
        Thread t3 = new Thread(new A(), "3");

        t1.start();
        try{
            t1.join();
        }catch (Exception e){

        }
        t2.start();
        try{
            t2.join();
        }catch (Exception e){

        }
        t3.start();
        try{
            t3.join();
        }catch (Exception e){

        }


    }
}

    class A implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName());
    }
}

或者您可以使用Executor Framework

public class Sequence {
    int valve = 1;
    public static void main(String[] args){
        Sequence s = new Sequence();
        ExecutorService es = Executors.newFixedThreadPool(3);

        List<Runnable> rList = new ArrayList<>();
        rList.add(new A(s));
        rList.add(new B(s));
        rList.add(new C(s));

        for(int i = 0; i < rList.size(); i++){
            es.submit(rList.get(i));
        }
        es.shutdown();

    }
}

class A implements Runnable{
    Sequence s;

    A(Sequence s){
        this.s = s;
    }

    public void run(){
        synchronized (s) {
            for (int i = 0; i < 10; i++) {
                while (s.valve != 1) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                s.valve = 2;
                s.notifyAll();
            }
        }
    }
}

class B implements Runnable{
    Sequence s;

    B(Sequence s){
        this.s = s;
    }

    public void run() {
        synchronized (s) {
            for (int i = 0; i < 10; i++) {
                while (s.valve != 2) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                s.valve = 3;
                s.notifyAll();
            }
        }
    }
}

class C implements Runnable{
    Sequence s;

    C(Sequence s){
        this.s = s;
    }

    public void run() {
        synchronized (s) {
            for(int i = 0; i < 10; i++) {
                while (s.valve != 3) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("C");
                s.valve = 1;
                s.notifyAll();
            }
        }
    }
}

在第一种情况下,每个线程的连接会导致线程彼此等待。在第二种情况下,列表存储线程,执行程序一个接一个地执行它们,创建3个线程

另一种方法是只存在一个可运行的类,并且线程之间的通信是通过主类中的静态变量和runnable类中的变量完成的。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Seq {
    int i = 1;
    public static void main(String[] args){
        Seq s = new Seq();
        Common c1 = new Common(s, 1);
        Common c2 = new Common(s, 2);
        Common c3 = new Common(s, 3);

        List<Runnable> l = new ArrayList<>();
        l.add(c1);
        l.add(c2);
        l.add(c3);

        ExecutorService es = Executors.newFixedThreadPool(3);
        for(int i = 0; i < 3; i++){
            es.submit(l.get(i));
        }
        es.shutdown();
    }
}

class Common implements Runnable{
    Seq s;
    int o;

    Common(Seq s, int o){
        this.s = s;
        this.o = o;
    }

    public void run(){
        synchronized (s) {
            for (int z = 0; z < 100; z++) {
                if(s.i > 3)
                    s.i = 1;
                while (s.i != o) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(o);
                s.i++;
                s.notifyAll();
            }
        }
    }
}

答案 6 :(得分:0)

解决这个问题的最简单的解决方案可以是以下方式:

public class PrintInOrder implements Runnable {

private int valueToPrint;
private int id;
private static int turn = 1;
private static int RESET_TURN_THRESHOLD = 3;

public PrintInOrder() {
    this.valueToPrint = -1;
}

public PrintInOrder(int id, int val) {
    this.id = id;
    this.valueToPrint = val;
}

@Override
public void run() {
        while(true) {
            if (turn == this.id) {
                System.out.println(Thread.currentThread().getName() + "::::" + valueToPrint);
                turn++;
            }
            if (turn > RESET_TURN_THRESHOLD) {
                turn = 1;
            }
        }

}

public static void main(String []args) {
    Thread t1 = new Thread(new PrintInOrder(1, 1));
    t1.setName("THREAD-1");
    t1.start();
    Thread t2 = new Thread(new PrintInOrder(2, 2));
    t2.setName("THREAD-2");
    t2.start();
    Thread t3 = new Thread(new PrintInOrder(3, 3));
    t3.setName("THREAD-3");
    t3.start();
}

}

/*
OUTPUT::::
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
...
*/

答案 7 :(得分:0)

这是我的解决方法-

我创建了三个线程,每个线程都知道它需要打印什么以及打印之后的内容。

我还创建了一个NLock类,其中包含需要打印的下一个单词。

只要线程能够获取NLock锁,它就会检查 如果轮到他了,那么它会打印单词并设置要在NLock中打印的下一个值,否则会等到轮到他为止

public class SynchronizeThreeThreads {

    public static void main(String args[]) throws InterruptedException {
        NLock lock=new NLock("A");
        Thread a =new Thread(new PrintInOrder("A","B",lock));
        Thread b =new Thread(new PrintInOrder("B","C",lock));
        Thread c =new Thread(new PrintInOrder("C","A",lock));

        a.start();
        b.start();
        c.start();
        c.join(); // Once all is done main thread will exit
        System.out.println("Done");
    }
}

class NLock{
     private String value;

     public NLock(String value) {
         this.value=value;
     }

     public String getValue() {
         return value;
     }

     public void setValue(String next) {
         this.value=next;
     }

}

class PrintInOrder implements Runnable{

    private String word;

    private String next;

    private NLock lock;

    public PrintInOrder(String word, String next,NLock lock){
        this.word=word;
        this.next=next;
        this.lock=lock;
    }

    @Override
    public void run() {
        int i=0;
        while(i<3) {
            synchronized (lock) {
                try {
                    //Check if it's my turn
                    if(lock.getValue().equals(word)) {
                        System.out.println(this.word);
                        //Set what next needs to be printed
                        //So that when that thread wakes up it knows that it's his turn
                        lock.setValue(next);
                        i++;
                        lock.notifyAll();
                        Thread.sleep(100);
                    }
                    else //Nope not my turn wait
                        lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

下面是输出

A 乙 C 一种 乙 C 一种 乙 C 完成

答案 8 :(得分:-1)

我认为使用join实现这一点更简单。 例如:

    public static void main(String[] args) {    
    final Thread t1 = new Thread("t1") {
        @Override
        public void run() {
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    final Thread t2 = new Thread(t1, "t2") {
        @Override
        public void run() {
            t1.start();
            try {
                t1.join();
            } catch ( InterruptedException e ) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    Thread t3 = new Thread(t2, "t3") {
        @Override
        public void run() {
            t2.start();
            try {
                t2.join();
            } catch ( InterruptedException e ) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    t3.start();

}

答案 9 :(得分:-1)

这是我的解决方案,请尝试让我知道

package thread;

class SyncPrinter {
    public static void main(String[] args) {
        SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
        SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
        SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
        SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);

        printAction1.setDependentAction(printAction4);
        printAction2.setDependentAction(printAction1);
        printAction3.setDependentAction(printAction2);
        printAction4.setDependentAction(printAction3);

        new Thread(printAction1, "T1").start();;        
        new Thread(printAction2, "T2").start();
        new Thread(printAction3, "T3").start();     
        new Thread(printAction4, "T4").start();



    }
}

class SyncPrinterAction implements Runnable {

    private volatile boolean dependent;
    private SyncPrinterAction dependentAction;
    int[] data;

    public void setDependentAction(SyncPrinterAction dependentAction){
        this.dependentAction = dependentAction;

    }

    public SyncPrinterAction( int[] data, boolean dependent) {
        this.data = data;
        this.dependent = dependent;
    }

    public SyncPrinterAction( int[] data, SyncPrinterAction dependentAction, boolean dependent) {
        this.dependentAction = dependentAction;
        this.data = data;
        this.dependent = dependent;
    }

    @Override
    public void run() {
        synchronized (this) {

            for (int value : data) {

                try {
                    while(dependentAction.isDependent())
                        //System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
                    wait(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                dependentAction.setDependent(true);

                System.out.println(Thread.currentThread().getName() + " :: " +value);
                dependent = false;
            }

        }

    }

    private void setDependent(boolean dependent) {
        this.dependent = dependent;

    }

    private boolean isDependent() {
        return dependent;
    }

}