fork download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.util.*;
  4. import java.util.concurrent.CopyOnWriteArrayList;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. import java.util.function.Consumer;
  8.  
  9. class Ideone
  10. {
  11. private static final Random RANDOM = new Random();
  12. public static void main(String[] args) {
  13. /*
  14.   Service A 01 03 1
  15.   Service B 02 03 2
  16.   Service C 03 04 3
  17.   Service D 04 05 4
  18.   Service E 05 07 5
  19.   Service F 06 07 6
  20.   Service G 07 (null) 7*/
  21. CallManager manager = new CallManager();
  22. manager.addService(simpleRunnable("A"), "A");
  23. manager.addService(simpleRunnable("B"), "B");
  24. manager.addService(simpleRunnable("C"), "C", "A", "B");
  25. manager.addService(simpleRunnable("D"), "D", "C");
  26. manager.addService(simpleRunnable("E"), "E", "D");
  27. manager.addService(simpleRunnable("F"), "F");
  28. manager.addService(simpleRunnable("G"), "G", "E", "F");
  29.  
  30. manager.run();
  31. }
  32.  
  33. // create some simple pseudo service
  34. private static Runnable simpleRunnable(String s) {
  35. return () -> {
  36. System.out.printf("running service %s%n", s);
  37. try {
  38. Thread.sleep(RANDOM.nextInt(2000));
  39. } catch (InterruptedException e) {
  40. e.printStackTrace();
  41. }
  42. };
  43. }
  44. }
  45.  
  46. class CallManager {
  47. List<Service> services = new ArrayList<>();
  48. ExecutorService executorService = Executors.newFixedThreadPool(4);
  49.  
  50. void addService(Runnable r, String serviceName, String... preconditions) {
  51. services.add(new Service(r, serviceName, this::preconditionFulfilled, preconditions));
  52. }
  53.  
  54. void run() {
  55. for (Iterator<Service> serviceIterator = services.iterator(); serviceIterator.hasNext(); ) {
  56. Service service = serviceIterator.next();
  57. if (service.arePreconditionsFulfilled()) {
  58. executorService.submit(service);
  59. serviceIterator.remove();
  60. }
  61. if (services.isEmpty()) {
  62. executorService.shutdown();
  63. }
  64. }
  65. }
  66.  
  67. private synchronized void preconditionFulfilled(String name) {
  68. System.out.printf("service %s finished%n", name);
  69. for (Iterator<Service> serviceIterator = services.iterator(); serviceIterator.hasNext(); ) {
  70. Service service = serviceIterator.next();
  71. service.preconditionFulfilled(name);
  72. if (service.arePreconditionsFulfilled()) {
  73. executorService.submit(service);
  74. serviceIterator.remove();
  75. }
  76. }
  77. if (services.isEmpty()) {
  78. executorService.shutdown();
  79. }
  80. }
  81. }
  82.  
  83. class Service implements Runnable {
  84.  
  85. private final Runnable wrappedRunnable;
  86. private final String name;
  87. private final List<String> preconditions = new CopyOnWriteArrayList<>();
  88. private final Consumer<String> finishedNotification;
  89.  
  90. Service(Runnable r, String name, Consumer<String> finishedNotification, String... preconditions) {
  91. this.wrappedRunnable = r;
  92. this.name = name;
  93. this.finishedNotification = finishedNotification;
  94. this.preconditions.addAll(Arrays.asList(preconditions));
  95. }
  96.  
  97. @Override
  98. public void run() {
  99. wrappedRunnable.run();
  100. finishedNotification.accept(name);
  101. }
  102.  
  103. void preconditionFulfilled(String precondition) {
  104. preconditions.remove(precondition);
  105. }
  106. boolean arePreconditionsFulfilled() {
  107. return preconditions.isEmpty();
  108. }
  109. }
Success #stdin #stdout 0.14s 34908KB
stdin
Standard input is empty
stdout
running service A
running service B
running service F
service A finished
service F finished
service B finished
running service C
service C finished
running service D
service D finished
running service E
service E finished
running service G
service G finished