[英]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 的低级并发原语(例如wait
和notify
相比,它有助于保持并发代码的简洁和简单。 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.