为了账号安全,请及时绑定邮箱和手机立即绑定

同步简化.

同步简化.

POPMUISE 2022-08-17 10:05:37
我目前正在研究线程和同步。我试图用这个程序打印“A”2次,“B”1次,“C”打印4次,这基本上是有效的,但我想知道是否有一个更小,更简单的解决方案,比如将所有类放入一个或类似的东西中。下面是代码。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;    }
查看完整描述

2 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

尽管该任务不需要线程,但这里有一种使用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));

        }

    });


查看完整回答
反对 回复 2022-08-17
?
长风秋雁

TA贡献1757条经验 获得超7个赞

正如第一条评论所说,您的任何对象之间都没有进行任何同步。也许通过更改启动线程的顺序(首先 C,然后是 B,然后是 A),这可能会变得很明显。

要使线程之间的调度正常工作,您需要:

  • 找到一个对两个线程都可见的对象,以便两个线程都可以在该对象上等待()和 notify()。

  • 建立将导致等待停止的条件,并在一段时间内将其放入()

所以你得到一些:

while (countA < 2) AClass.class.wait();

在 B 线程中(并在循环中捕获中断异常,不要传播)

并在您放置的 A 线程中

AClass.class.notify();

在打印循环退出后。

您可以(在工业环境中,大多数情况下应该)将AClass.class替换为专用于该目的的同步对象(并且已对两个线程都可见)。

while() 是必要的,因为所谓的“虚假唤醒”:如果 notify() 导致它退出,则 wait() 将退出,但它也可以在没有发出此类 notify() 的情况下退出。

最后,请注意,while() 循环中的条件从线程 B 访问 countA 字段,而线程 A 可能正在更新它。对于简单整数,这可能仍然是万无故障的,但对于更复杂的评估,这本身就是争用条件错误的潜在来源,因此需要依次同步这些访问。另请注意,如果线程A由于任何原因崩溃,则可能永远不会成为真,因此这不是设置内容的最可靠方法,因为它会导致系统挂起。while(countA<2)

如果所有这些都更像是胡言乱语而不是英语,你应该首先尝试找到一个关于线程的体面教程,并仔细研究。


查看完整回答
反对 回复 2022-08-17
  • 2 回答
  • 0 关注
  • 86 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号