Question

I'm working on a java webserver which calls a web service. I'm trying to write some code in a nicer.

I've got 2 similar functions, only one thing changes : the function i have to call depending what i want to do.

public Object updateDef() {
    ExecutorService pool = Executors.newFixedThreadPool(20);
    List<Callable<String>> tasks = new ArrayList<Callable<String>>();

    logger.info("Updating surv def...");

    for (final Surv surv : Client.activatedSurvs) {
        final Client client = new Client(surv.getName(), surv.getPassword());

        tasks.add(new Callable<String>() {
            public String call() throws Exception {
                HERE -> client.updateDef(surv);
                return surv.getId();
            }
        });
        client.destroy();
    }

    List<Future<String>> results = null;
    try {
        results = pool.invokeAll(tasks);
        for (Future<String> future : results) {
            future.get();

        }
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    pool.shutdown();

    return null;
}

And the other one :

public Object updateStats() {
    ExecutorService pool = Executors.newFixedThreadPool(20);
    List<Callable<String>> tasks = new ArrayList<Callable<String>>();

    logger.info("Updating surv Stats...");

    for (final Surv surv : Client.activatedSurvs) {
        final Client client = new Client(surv.getName(), surv.getPassword());

        tasks.add(new Callable<String>() {
            public String call() throws Exception {
                HERE -> client.updateStats(surv).toString();
                return surv.getId();
            }
        });
        client.destroy();
    }

    List<Future<String>> results = null;
    try {
        results = pool.invokeAll(tasks);
        for (Future<String> future : results) {
            future.get();
        }
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    pool.shutdown();

    return null;
}

So the 2 functions are updateStats and updateDef from class A with a static list from B. The problem is that I've to pass a parameter which is an existing element from this list.

=> A.updateStats(B.list.get(X));

=> A.updateDef(B.list.get(X));

I visited this link How to pass a function as a parameter in Java? but without success

Any idea ?

Was it helpful?

Solution

Your object is to replace:

tasks.add(new Callable<String>() {
        public String call() throws Exception {
            client.updateStats(surv).toString();
            return surv.getId();
        }
    });

With

tasks.add(new Callable<String>() {
        public String call() throws Exception {
            doSomething(client, surv);
            return surv.getId();
        }
    });

Which can be done by defining an Interface:

public interface ClientUpdate {
    public void performUpdate(Client client, Surv surv);
}

Then, use this interface as a parameter to your method:

public Object updateStats() {

Becomes

public Object update(ClientUpdate updater) {

Then use it in your callable

tasks.add(new Callable<String>() {
        public String call() throws Exception {
            updater.performUpdate(client, surv);
            return surv.getId();
        }
    });

Then implement it:

updateStats();

becomes:

update(new ClientUpdate() {
    public void performUpdate(Client client, Surv surv) {
        client.updateStats(surv).toString();
    }
});

Similarly for updateDef();

OTHER TIPS

You could use a Strategy pattern or Functors. Honestly, I think I would just factor the common pieces out into shared methods.

Easy - pass in the Callable and don't repeat all the boilerplate around it.

public Object foo(Callable<String> callable) {
    ExecutorService pool = Executors.newFixedThreadPool(20);
    List<Callable<String>> tasks = new ArrayList<Callable<String>>();

    logger.info("Updating surv def...");

    for (final Surv surv : Client.activatedSurvs) {
        final Client client = new Client(surv.getName(), surv.getPassword());
        tasks.add(callable;
        client.destroy();
    }

    List<Future<String>> results = null;
    try {
        results = pool.invokeAll(tasks);
        for (Future<String> future : results) {
            future.get();

        }
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    pool.shutdown();

    return null;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top