简体   繁体   English

如何编写多线程程序的最佳方式

[英]How to write below multithreaded program best way

I am new to multithreading, and get to know about the functionality of wait, notify and notifyAll.我是多线程的新手,了解了 wait、notify 和 notifyAll 的功能。 I want three threads to execute one after another and print alphabets from A to Z. I have tried below code and it seems working also, but I doubt if this is the best possible way to tackle the problem.我希望三个线程一个接一个地执行并从 A 到 Z 打印字母。我尝试过下面的代码,它似乎也有效,但我怀疑这是否是解决问题的最佳方法。 Is there any other way, I can make it more simple and better ?有没有其他方法,我可以让它更简单更好? It seems some portion of my code is repeating.我的代码的某些部分似乎在重复。

package demo.threading;

class Flags {

    boolean flagA = true;
    boolean flagB = false;
    boolean flagC = false;

}

class Container {

    Flags flags = new Flags();
    int charVal = (int) 'A';

    void producer1() {

        try {
            while (charVal <= (int) 'Z') {
                synchronized (this) {
                    if (!flags.flagA)
                        wait();
                    else {
                        System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
                        flags.flagA = false;
                        flags.flagB = true;
                        charVal++;
                        notifyAll();
                        Thread.sleep(1000);
                    }
                }
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

    }

    void producer2() {

        try {
            while (charVal <= (int) 'Z') {
                synchronized (this) {
                    if (!flags.flagB)
                        wait();
                    else {
                        System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
                        flags.flagB = false;
                        flags.flagC = true;
                        charVal++;
                        notifyAll();
                        Thread.sleep(1000);
                    }
                }
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    void producer3() {

        try {
            while (charVal <= (int) 'Z') {
                synchronized (this) {
                    if (!flags.flagC)
                        wait();
                    else {
                        System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
                        flags.flagC = false;
                        flags.flagA = true;
                        charVal++;
                        notifyAll();
                        Thread.sleep(1000);
                    }
                }
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

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

        Container container = new Container();

        Thread t1 = new Thread(() -> container.producer1(), "Thread 1");
        Thread t2 = new Thread(() -> container.producer2(), "Thread 2");
        Thread t3 = new Thread(() -> container.producer3(), "Thread 3");

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

    }
}

Output should be :输出应该是:

Thread 1 Produced : A
Thread 2 Produced : B
Thread 3 Produced : C
Thread 1 Produced : D
Thread 2 Produced : E
Thread 3 Produced : F

As pointed out before, if you want to do this "one after another", you actually don't need multiple threads.如前所述,如果您想“一个接一个”地执行此操作,您实际上不需要多个线程。 However, you can achieve this by using a Semaphore :但是,您可以通过使用Semaphore来实现这一点:

int numberOfThreads = 3;
Semaphore semaphore = new Semaphore(1);

for (int i = 1; i <= numberOfThreads; i++) {
    new Thread(() -> {
        try {
            semaphore.acquire();
            for (char c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()) {
                System.out.println(Thread.currentThread().getName() 
                        + " produced: " + c + ".");
            }
        } catch (InterruptedException e) {
            // NOP
        } finally {
            semaphore.release();
        }
    }, "Thread " + i).start();
}

I recommend exploring java.util.concurrent which is available since Java 5. It's a great help to keep your concurrent code concise and simple compared with Java's low-level concurrency primitives such as wait and notify .我建议探索java.util.concurrent ,它从 Java 5 开始可用。与 Java 的低级并发原语(例如waitnotify相比,它有助于保持并发代码的简洁和简单。 If you're really interested in that topic, Brian Goetz's "Java Concurrency in Practice" is a must-read.如果您真的对该主题感兴趣, Brian Goetz 的“Java 并发实践”是必读的。

EDIT:编辑:

public class ConcurrentAlphabet {

    private volatile Thread current;

    public static void main(String[] args) {
        new ConcurrentAlphabet().print(3,
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray());
    }

    public void print(int numberOfThreads, char[] alphabet) {
        Thread[] threads = new Thread[numberOfThreads];

        for (int i = 1; i <= numberOfThreads; i++) {
            int offset = i - 1;
            threads[offset] = new Thread(() -> {
                Thread me = Thread.currentThread();
                Thread next = threads[(offset + 1) % numberOfThreads];

                for (int index = offset; index < alphabet.length; index += numberOfThreads) {
                    synchronized (this) {
                        while (me != current) {
                            try {
                                wait();
                            } catch (InterruptedException e) { /* NOP */ }
                        }

                        System.out.println(me.getName() + " produced: " + alphabet[index] + ".");
                        current = next;
                        notifyAll();
                    }
                }
            }, "Thread " + i);
        }

        current = threads[0];

        for (Thread t : threads) {
            t.start();
        }
    }

}
package demo.thread;

public class ABCPuzzle {

    private static class RunnableImpl implements Runnable {

        private String nextThread;
        private ExecServ execServ;

        public RunnableImpl(ExecServ execServ, String nextThread) {
            this.execServ = execServ;
            this.nextThread = nextThread;
        }

        @Override
        public void run() {

            String threadName = Thread.currentThread().getName();

            synchronized (execServ) {
                try {
                    while (true) {
                        if (execServ.key > 'Z')
                            break;

                        if (threadName.equals(execServ.current)) {
                            System.out.println(threadName + " consuming "  + execServ.key);
                            Thread.sleep(1000);
                            execServ.key++;
                            execServ.current = nextThread;
                            execServ.notifyAll();
                        } else
                            execServ.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class ExecServ {
        private String current, next;
        private char key = 'A';
    }

    public static void main(String[] args) {

        ExecServ execServ = new ExecServ();
        execServ.current = "t1";

        Thread t1 = new Thread(new RunnableImpl(execServ, "t2"), "t1");
        Thread t2 = new Thread(new RunnableImpl(execServ, "t3"), "t2");
        Thread t3 = new Thread(new RunnableImpl(execServ, "t4"), "t3");
        Thread t4 = new Thread(new RunnableImpl(execServ, "t1"), "t4");

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

    }
}

Output :输出:

t1 consuming A
t2 consuming B
t3 consuming C
t4 consuming D
t1 consuming E
t2 consuming F
t3 consuming G
t4 consuming H
t1 consuming I
t2 consuming J

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM