2013-02-14 53 views
0

我需要使用并发性的java任务的帮助。我遇到的问题是get方法,我找不到任何问题。但是,它感觉它没有被正确访问,或者它没有按照它应该做的那样去做。总之,问题在于我得到了所有的金属,但我没有给消费者,我不知道这是怎么回事。让我知道是否需要提供任何其他信息。java并发性,生产者(代理)和消费者

每个经纪人都维持着所有三种金属的库存,但它们只是其中一家的“供应商”,称其为“专业”。炼油厂不时向其供应商提供一批精炼金属交付给经纪人。例如,炼油商可能向黄金供应商交付30盎司黄金。消费者定期向经纪人下订单。每个订单指定每种金属的盎司数量。它可以与任何经纪人一起放置。如果可能的话,经纪人将从自己的股票中填写订单。如果金属M的供应商由于手头没有足够的M而无法填写订单,它只是等待,直到它从炼油厂获得更多。但是,如果它是一些其他金属短缺,它试图通过与该金属的供应商进行交易来获得它。为了简单起见,我们将假设有些不切实际的是,盎司黄金,铂金或铀都是同等价值的。也就是说,三盎司的黄金可以交换三盎司的铀或三盎司的铂金。

对不起,我不能显示使用BrokerImplementation的类。我不能,因为他们都是.class文件,并不认为上传位代码会有帮助。

在此先感谢您提供的任何帮助。

// This class overrides all it's methods from the Broker interface 
public class BrokerImplementation implements Broker, IBM { 

int specialty; 
int[] metals = {0, 0, 0}; 

/** 
* The constructor takes a single integer parameter, the code for the metal 
* which this broker supplies. 
* 
* @param specialty 
*/ 
public BrokerImplementation(int specialty) { 
    this.specialty = specialty; 
} 

/** 
* This method is used by Project2.main to audit the global state when the 
* system shuts down. The Broker should fill in result with the amount of 
* each metal it has on hand. 
* 
* @param result 
*/ 
@Override 
public void getAmountOnHand(int[] result) { 

    //GOLD, PLATINUM, URANIUM are are constants in the IBM interface 
    //which correspond to the indexes {0, 1, 2} 
    result[GOLD] = metals[GOLD]; 
    result[PLATINUM] = metals[PLATINUM]; 
    result[URANIUM] = metals[URANIUM]; 
} 

/** 
* A consumer calls this method to place an order. The argument is a 
* three-element array indicating the number of ounces of gold, platinum, 
* and uranium desired. It should return only when the order has been 
* filled. 
* 
* @param metals 
*/ 
@Override 
public void get(int[] order) { 

    for(int i = 0; i < 3; i++){ 
    if (metals[i] > order[i]) { 
     metals[i] -= order[i]; 
    } else { 
     this.swap(i, order[i] - metals[i]); 
     this.get(order); 
     try { 
      wait(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(BrokerImplementation.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     notifyAll(); 
    } 
    } 
} 

/** 
* Another broker calls this method to swap one metal for another. The what 
* argument indicates one of the metals; the other one is the metal in which 
* this broker specializes. The ounces argument indicates how many ounces to 
* swap. 
* 
* @param what 
* @param ounces 
*/ 
@Override 
public void swap(int what, int ounces) { 

    synchronized (this) { 
     if (metals[specialty] >= ounces) { 

      metals[specialty] -= ounces; 
      metals[what] += ounces; 

     } else { 
      notifyAll(); 
      try { 
       wait(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(BrokerImplementation.class.getName()).log(Level.SEVERE, null, ex); 
      } 

     } 
    } 
} 

/** 
* The refiner calls this method to deliver a load of metal to the broker. 
* The argument ounces is a number of ounces. The metal is the one this 
* broker supplies. 
* 
* @param ounces 
*/ 
@Override 
public void deliver(final int ounces) { 
    System.out.println("available " + metals[specialty]); 
    metals[specialty] += ounces; 
} 

回答

1

特别注意get(int[] order)方法有几件事情你没有考虑。既然你在你的问题中提到了多线程,我认为多线程可以同时调用这个方法。鉴于这个事实,您没有考虑到同步访问共享资源metals[]。操作-=不是线程安全的,也不是您对该数组的迭代。另外,当您添加同步时,如果您关注性能,则尝试最小化您的同步内容,因为this上的同步大型块可能会影响性能。

编辑:我也建议(虽然你没有要求这样),你没有wait()在你的synchronized块中。这将导致死锁,因为同步块内的线程在等待时将阻止metals[]

+0

为了扩展这一点,您可能需要考虑同步访问金属而不是get()方法。我看到的问题是,您可以通过三种方式修改金属:获得交货,与供应商交换或填写订单。由于所有这些都可能同时发生,并且所有参考资料都是相同的,所以资源(金属)应该同步。另外,正如@nattyddubbs所说的那样,我会避免同步“this”的方法。相反,在特定的共享资源上尽量少用一个同步块。 – CodeChimp 2013-02-14 17:29:20

+0

我会如何去关于金属上的同步,是我试过在金属上做过之前,但它给了我一个警告,它被翻译成一些RuntimeExceptions – oscarMg 2013-02-15 22:43:36

+0

这就是我做到的。 '同步(金属){}',我只是想知道这是你的意思还是我完全不在。 – oscarMg 2013-02-15 23:09:39