“用餐哲学家”在Java中使用Future

时间:2013-11-26 11:29:19

标签: java concurrency future

我正试图用Java解决使用Future的哲学问题。

 public class Philo implements Callable<PhiloStatus> {

    private PhiloStatus status;
    private Philo leftPhilo;
    private Philo rightPhilo;

    private String name;

    public Philo(String name) {
        status = PhiloStatus.THINKING;

        this.name =name;
    }



    public void setLeftPhilo(Philo leftPhilo) {
        this.leftPhilo = leftPhilo;
    }

    enter code here

    public void setRightPhilo(Philo rightPhilo) {
        this.rightPhilo = rightPhilo;
    }



    @Override
    public PhiloStatus call() throws Exception {

        if (leftPhilo.getStatus() == PhiloStatus.THINKING
                && rightPhilo.getStatus() == PhiloStatus.THINKING) {

            this.status =PhiloStatus.DINING;
            System.out.println("Dininig "+this);
            return PhiloStatus.DINING;

        }

        this.status =PhiloStatus.THINKING;
        System.out.println("Thinking "+this);
        return PhiloStatus.THINKING;
    }

    public PhiloStatus getStatus() {

        return status;

    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return name;
    }

}

该计划的起点

public class Start {

    /**
     * @param args
     */
    public static void main(String[] args) {


        ExecutorService executorService = Executors.newFixedThreadPool(5);
        Philo[] philosophers = new Philo[5];


        for (int i = 0; i < 5; ++i)
          philosophers[i] = new Philo(""+i);
        for (int i = 0; i < 5; ++i) {
          philosophers[i].setLeftPhilo(philosophers[(i + 4) % 5]);
          philosophers[i].setRightPhilo(philosophers[(i + 1) % 5]);

          executorService.submit( philosophers[i]);

        }



    }

}

但似乎一旦Callable完成执行,它就会返回相同的结果。

我现在怀疑使用Future可能无法解决这个问题?

任何人都可以对此有所了解。

2 个答案:

答案 0 :(得分:1)

class Philo implements Runnable{

   @Override
   public void run(){
       while(true){

           if(Thread.interrupted()){
               break;
           }

           //dining logic
       }

   }
}

解决方案可以是循环,执行直到某人中断Philosopher

答案 1 :(得分:1)

Callable计算结果一次,然后返回此计算的值 。因此,如果您想再次计算某些内容,则需要再次运行Callable。

void diningAttempt() {
  Future<PhiloStatus>[] results = new Future<PhiloStatus>[philosophers.length];
  for (int i = 0; i < philosophers.length; ++i) {
    results[i] = executor.submit(philosophers[i]);
  }
  for (int i = 0; i < philosophers.length; ++i) {
    System.out.println(results[i].get());
  }
}

然后在其他地方:

while (dining) {
  diningAttempt();
}

正如您可能看到的,这与“Dining Philosopher”问题实际描述的内容略有不同,这就是线程能够随时做某事的问题,就像在这种情况下一样你有分开的用餐尝试,然后很可能一直成功。

如果您希望这些线程实际锁定,您需要让它们能够一直并行运行,这意味着Callable不是模拟此问题的正确方法。然而,您的尝试有一个值得学习的宝贵经验:如果您设法将您的工作分成不同的批次,那么线程就不太可能锁定。这就是Executor首先被发明的原因。