【问题标题】:Thread objects not syncing线程对象不同步
【发布时间】:2015-01-21 20:49:22
【问题描述】:

所以我编写了这个程序来运行这个机器人类的多个线程,使用 cyclicbarrier 来同步线程。由于我对循环障碍知之甚少,我认为它会自动同步我的线程,但似乎不是。我需要做什么才能让我的机器人线程根据我的进度整数值进行同步?

public class Robot implements Runnable{
public static final int on = 0x0001;
public static final int clockwise = 0x0002;
public static final int counter = 0x0004;
int  opcode;
int moveCount = 0;
int rotation, increment, progress = 0;
boolean CW;

ProgressBar prgBar;
CyclicBarrier cyclicBarrier;
Controller c;
Motor m;

public Robot(CyclicBarrier cyclicBarrier, Motor m)
{
    opcode = 0;
    this.cyclicBarrier = cyclicBarrier;
    this.m = m;
}




public void run(){
    System.out.println("Running: ");

    try {
        while(progress <= 24){
            i = m.Engage(this, i, increment/4);
            prgBar.setProgress(this, progress);
        }
        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 1");
        cyclicBarrier.await();

        while(progress <= 49){
            i = m.Engage(this, i, increment/2);
            prgBar.setProgress(this, progress);
        }
        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 2");
        cyclicBarrier.await();

        while(progress <= 74){
            i = m.Engage(this, i, ((increment/4)*3));
            prgBar.setProgress(this, progress);
        }
        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 3");
        cyclicBarrier.await();

        while(progress <= 99){
            i = m.Engage(this, i, increment);
            prgBar.setProgress(this, progress);
        }
        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 4");
        cyclicBarrier.await();

    } catch (Exception e){
        e.printStackTrace();
    }
    prgBar.setProgress(this, progress);
    System.out.println("Engaging: ");
}

公共类控制器{

public static void main(String[] args){
    CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
    Motor m = new Motor();


    Robot xRob = new Robot(cyclicBarrier, m);
    Robot yRob = new Robot(cyclicBarrier, m);
    Robot zRob = new Robot(cyclicBarrier, m);

    Thread xRobThread = new Thread(xRob);
    Thread yRobThread = new Thread(yRob);
    Thread zRobThread = new Thread(zRob);

    boolean clockwise = true, counterClockwise = false;




    m.setMotor(clockwise, 14400, xRob);
    m.setMotor(clockwise, 7200, yRob);
    m.setMotor(counterClockwise, 28800, zRob);

    xRobThread.start();
    yRobThread.start();
    zRobThread.start();

    try {
        xRobThread.join();
        yRobThread.join();
        zRobThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }


    System.out.printf("x = %d y = %d z = %d\n\n", xRob.moveCount, yRob.moveCount, zRob.moveCount);

}
}

【问题讨论】:

  • 由于我对 cyclicbarrier 了解甚少,我以为它会自动同步我的线程,但似乎不会。 你是认真的吗?请阅读 javadoc。
  • 我用了过去式,我现在明白了,事实并非如此。我也读了好几遍,但对我来说没有任何意义,因为我的代码与他们的示例并不完全相同。他们也没有真正解释如何根据变量在障碍点之间拆分工作。
  • 问题是,你认为“同步我的线程”应该是什么意思?也就是说,你期望这个类做什么?相反,它做了什么?为什么这让你感到惊讶?如果您向我们展示完整的程序,它可能会有所帮助。您只向我们展示了一个使用 CyclicBarrier 的类。您没有向我们展示 CyclicBarrier 的创建,也没有向我们展示运行您的 Robot 类的任何线程的创建。
  • 所以我有一个 m.Engage(this) 在屏障之前运行,它启动了一个循环增量时间的循环。我希望循环一直持续到他的线程的某个百分比,等待然后继续循环直到另一个障碍,在达到 100% 之前循环了 4 次,我已经更新了我的代码。
  • P.S.:你也可以删减这个例子。您没有向我们展示任何调用 setOn() 的代码,而 setOn() 是您向我们展示的唯一调用 Set() 的代码。您没有向我们展示任何调用 Validate() 或 rotate() 的代码。您已经向我们展示了所有这些方法,但它们看起来都与“同步我的线程”的问题有关。换句话说,您的示例与 SSCCE (sscce.org) 相差甚远。

标签: java multithreading cyclicbarrier


【解决方案1】:

我将barrier1设置为~25%,将barrier2设置为~50%,依此类推,我想在循环中走多远,当每个循环到达末尾时,我通过输出lop中的当前位置来更新i线。我一遍又一遍地做同样的事情,直到进度结束。

public void run(){
    System.out.println("Running: ");
    barrier1 = increment/4;
    barrier2 = increment/2;
    barrier3 = ((increment/4)*3);
    barrier4 = increment;
    try {
        i = m.Engage(this, i, barrier1);
        prgBar.setProgress(this, progress);

        System.out.println("Sleeping: ");
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 1");
        cyclicBarrier.await();


        i = m.Engage(this, i, barrier2);
        prgBar.setProgress(this, progress);

        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 2");
        cyclicBarrier.await();


        i = m.Engage(this, i, barrier3);
        prgBar.setProgress(this, progress);

        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+ " waiting at barrier 3");
        cyclicBarrier.await();


        m.Engage(this, i, barrier4);
        prgBar.setProgress(this, progress);

    } catch (Exception e){
        e.printStackTrace();
    }
    prgBar.setProgress(this, progress);
    System.out.println(Thread.currentThread().getName()+ " closing.");
    Thread.currentThread().interrupt();
    System.out.println("Engaging: ");
}

【讨论】:

    【解决方案2】:

    程序运行时会做什么?你期望它做什么? (即,您认为“同步我的线程”是什么意思?)

    至少,您的更新现在包含足够的信息让我猜测,我猜测程序挂起。您的 main() 例程为四方创建一个新的 CyclicBarrier,然后创建三个线程。这些线程中的每一个都调用 cyclicBarrier.await(),但我没有看到任何第四方。在四个线程调用 await() 之前,屏障不会打开。


    附加信息:

    好的,假设您有一个循环,可以实现某种“进步”。您可以通过执行以下操作让第一个达到特定进度阈值的线程等待其他线程赶上:

    double progress = 0.0;
    static final double CHECKPOINT = 0.5;
    static final double FINISHED = 1.0;
    boolean reachedCheckpoint = false;
    
    while (progress < FINISHED) {
        progress = makeSomeProgress();
        if (! reachedCheckpoint && progress >= CHECKPOINT) {
            cyclicBarrier.await();
            reachedCheckpoint = true;
        }
    }
    

    显然,如果您想拥有多个检查点,程序会稍微复杂一些,但这是基本思想。请记住,构造 CyclicBarrier 的“参与方”的数量必须完全等于实际使用它的线程数。

    【讨论】:

    • 我试图让线程在完成进度的某个百分比时等待,但从那时起我就很难在 for 循环中间停止我的程序并在那里重新启动它我认为这是不可能的......在程序刚刚完成并以 100% 挂起之前,我并不介意,但线程会在不同的时间完成。
    • 好的,所以我只是尝试了一下,我觉得我真的很接近了。更新了我的机器人类代码。
    • 我最终在我的 run(); 方法调用的参数中更新了我的 i 和增量(我在 for 循环中使用);每次我达到某个阈值并点击 await 命令以等待其他人最终到达相同的障碍。您描述它的方式行不通,因为每次我调用取得进展的方法时,它都会完成我的整个循环。我想我会发布我自己的答案,即使它现在没有任何区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-02
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    相关资源
    最近更新 更多