我目前正在研究线程和同步。 我正在尝试使用此程序将“ A”打印两次,“ B”打印一次和“ C”打印四次,这基本上是可行的,但我想知道是否有更小,更简单的解决方案,例如将所有分为一个或类似的东西。
这是代码。
public class foo {
public static int countA = 0;
public static int countB = 0;
public static int countC = 0;
public static void main(String[] args) {
AThread athread = new AThread(new AClass());
BThread bthread = new BThread(new BClass());
CThread cthread = new CThread(new CClass());
athread.start();
bthread.start();
cthread.start();
}
static class AClass {
public synchronized void printA() throws InterruptedException {
if(countA == 2)
wait();
for(int i=1; i<3; i++) {
System.out.println("A"+i);
countA++;
}
}
}
static class BClass{
public synchronized void printB() throws InterruptedException {
if(countB == 1)
wait();
for(int i=1; i<2; i++) {
System.out.println("B"+i);
countB++;
}
}
}
static class CClass{
public synchronized void printC() throws InterruptedException {
if(countC == 4)
wait();
for(int i=1; i<5; i++) {
System.out.println("C"+i);
countC++;
}
}
}
static class AThread extends Thread {
AClass A = new AClass();
AThread(AClass a){
this.A = a;
}
public void run() {
try {
A.printA();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class BThread extends Thread {
BClass B = new BClass();
BThread(BClass b){
this.B = b;
}
public void run() {
try {
B.printB();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class CThread extends Thread {
CClass C = new CClass();
CThread(CClass c){
this.C = c;
}
public void run() {
try {
C.printC();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
答案 0 :(得分:1)
即使该任务不需要线程,这也是使用Java 8 CompletableFuture
在描述中编写代码的另一种方式CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
for (int i = 0; i < 2; i++) {
System.out.println("A" + (i + 1));
}
}).thenRunAsync(() -> {
System.out.println("B1");
}).thenRunAsync(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("C" + (i + 1));
}
});
答案 1 :(得分:0)
正如第一条评论所述,您的任何对象之间都没有任何同步。也许可以通过更改启动线程的顺序(首先是C,然后是B,然后是A)来改变这种情况。
要在线程之间进行调度以工作,您需要:
所以您会得到:
while (countA < 2) AClass.class.wait();
在B线程中 (并在循环中捕获InterruptedException,请勿传播)
并在您放置的A线程中
AClass.class.notify();
退出打印循环后。
您可以(并且在大多数情况下应使用工业设置)将AClass.class替换为专用于此目的的同步对象(并且这两个线程都可以看到该对象)。
while()是必需的,因为所谓的“虚假唤醒”:wait()将在notify()导致它退出的情况下退出,但也可以在没有notify()导致的情况下退出已发布。
最后,请注意,while()循环中的条件从线程B访问countA字段,而线程A可能正在更新它。对于简单的整数,这仍然可能是防故障的,但是对于更复杂的评估,这本身就是争用条件错误的潜在来源,因此,这些访问需要依次同步。另请注意,如果线程A由于任何原因而崩溃,while(countA<2)
可能永远不会成真,因此这是 不是 的最可靠的设置方法,因为它将导致系统崩溃。挂起。
如果所有这些都比英语更像乱语,则应首先尝试找到一个不错的线程教程,并仔细研究。