递归/多线程程序问题

时间:2010-04-15 22:16:56

标签: java multithreading recursion

我是Java和多线程的新手。我有以下问题:

我有两个名为Class AClass B的类在两个不同的线程中运行。

Class A的方法为onNewEvent()

调用该方法后,它会要求Class B做一些工作。一旦B类完成工作,它就会调用onJobDone()中定义的方法Class A

现在,问题就出现了:我想要的是在方法onJobDone()中创建一个新工作,然后再将其发送到Class B

这是我在执行顺序中做的(伪代码)

A.onNewEvent(){
    //create job
    //ask B to do it
    B.do()
}

B.do{
    // Do some stuff
    A.jobDone()
}

A.onJobDOne(){
    B.do()   //doItAgain

    // print message "Thank you for doing it"
}

问题是“谢谢你这样做”的消息永远不会被打印出来。实际上,当调用onJobDone()方法时,它会调用B.do(),因为B.do()非常快。它立即调用onJobDone(),因此执行流程永远不会出现在代码的PRINT MESSAGE部分。

我认为这是一个令人讨厌的多线程问题。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:3)

这不是一个多线程问题,你刚刚创建了一个无限循环。 B.do调用A.onJobDone调用B.do调用A.onJobDone等。因此执行永远不会到达打印消息行。你需要一个突破条件,以便在onJobDone中你可以决定你是否想要'doItAgain'。在某些时候,您将决定不再进行此操作,此时您的代码将到达打印消息行。

如果你描述了你想要实现的目标可能会有所帮助,我们可以给你一些关于实现它的最佳方法的指示。我不确定你试图解决问题的方式是不是最好的方式。

答案 1 :(得分:0)

这是一个建议

 A.onNewEvent(){
     //create job
    //ask B to do it
     B.do()

}

B.do{
    // Do some stuff
    A.onJobDone()
}

A.onJobDone(){
    // print message "Thank you for doing it" (B.do() has just completed, so it 
    //will print for every time you call B.do()
    if (shouldDoJobAgain()) //it should stop some time, right?
      B.do()

}

答案 2 :(得分:0)

调用类方法并不固有地与线程相关联。换句话说,在线程1中调用B.do()内的A.onNewEvent()仍将在线程1中执行。换句话说,可以从任何线程调用对象的方法。

要在给定线程中执行方法,您需要在线程的run方法中调用该方法。为了支持这一点,您需要定义:B上的方法,当有新作业时发出信号,B表示保存作业信息的字段(通常,您使用队列,但这里可以使用简单的整数)和正确地同步对B字段的访问。自从我在Java中完成此操作(可能存在竞争条件或某处死锁)以来,它已经有点了,但我相信以下应该工作

class A {
    ...
    public void onEvent() {
        b.addJob();
    }
    // careful about making onJobDone synchronized
    public void onJobDone() {
        // do it again
        b.addJob();
        ...
    }
}

class B extends Thread {
    A a;
    int jobCount;
    boolean work;

    ...
    public void run() {
        shouldWork(true);
        while (shouldWork()) {
            while (haveJobs()) {
                doingJob();
                ...
                didJob();
            }
            waitForWork();
        }
    }
    public synchronized void addJob() {
       ++jobCount;
       notify();
    }
    protected synchronized boolean haveJobs() {
        return jobCount > 0;
    }
    protected synchronized void doingJob() {
        /* could also decrement 'jobCount' in didWork(), in which case
           it will need to be made synchronized
         */
        --jobCount;
    }
    protected void didJob() {
        a.onJobDone();
    }
    protected synchronized void waitForWork() {
        while (! haveJobs()) {
            try {
                wait();
            } catch (Exception e) {
        }
    }
    public synchronized void shouldWork(boolean w) {
        work = w;
    }
    protected synchronized boolean shouldWork() {
        return work;
    }
}

要避免的主要问题是死锁。大多数同步方法不会导致死锁。 waitForWork调用wait,它会释放监视器,以便其他线程可以成功调用addJob

请注意,上述操作仍将永久运行,因为作业结束会导致安排新作业。与编码方式相比,优势在于A.onJobDone将完成,您将不会获得堆栈溢出。如果您希望每个A.onEvent使B处理n个作业,请将A定义为:

class A {
    int jobsPerEvent;
    int remainingJobs;
    ...
    public void onEvent() {
        synchronized (this) {
            remainingJobs += jobsPerEvent;
        }
        b.addJob();
    }
    public synchronized void jobsRemain() {
        return remainingJobs > 0;
    }
    public void onJobDone() {
        synchronized (this) {
            --remainingJobs;
        }
        // do it again
        if (jobsRemain()) {
            b.addJob();
        }
        ...
    }
}

答案 3 :(得分:0)

另一种方法是实现asynchronous method调用,将异步方法(B.do)重构为一个单独的类。

class B {
    A a;
    Set jobs;
    class BAlgo extends Thread {
        public void run() {
            // stuff originally in B.do
            ...
            done();
            jobs.remove(this);
        }
    }

    public void do() {
        BAlgo algo = this.new BAlgo();
        algo.start();
        jobs.add(algo);
    }
    protected void done() {
        a.onJobDone();
    }
    ...
}

我确定将do方法重构为实现算法的类是另一种模式,但我不确定它的名称。它不是bridge pattern,也不是template method pattern。它几乎遵循proxy模式,但并不完全。