The following is @paul-griffith's answer without a callback so futures can be accessed on the main thread and allow for simpler error handling:
from java.util.concurrent import CompletableFuture
from java.util.function import Consumer, Supplier
from functools import partial
from time import sleep
# Adapts a Python function to act as a Java "Consumer" functional interface
# Works when called directly or as a decorator with @ syntax
def java_consumer(func):
class PythonConsumer(Consumer):
def accept(self, t):
func(t)
return PythonConsumer()
# Adapts a Python function to act as a Java "Supplier" functional interface
def java_supplier(func):
class PythonSupplier(Supplier):
def get(self):
return func()
return PythonSupplier()
# Mock update function that just blocks for a fixed delay
def updateSize(row):
sleep(2)
return {"SIZE": row}
def runUpdates():
# Just some mock data to stick to the general structure of the existing code
tagData = system.dataset.toDataSet(["a", "b"], [[1, 2], [2, 3], [3, 4]])
pyTagData = system.dataset.toPyDataSet(tagData)
futures = []
for row in pyTagData:
# Some antics here to adapt types and wrap up default arguments
supplier = java_supplier(partial(updateSize, row))
# supplyAsync is a static method that will use Java's built in ForkJoinPool thread pool
futures.append(CompletableFuture.supplyAsync(supplier))
# the callback is no longer needed with the use of .get()
CompletableFuture.allOf(futures).get()
for i, future in enumerate(futures):
print i, future.get()
runUpdates()