2

I am trying to call method in new thread which will return something after delay using callable. It is falling due to IllegalMonitorStateException Is it possible to encapsulate thread service that way, when I will just create instance of class, call method and that method will return object with delay? Thank you in advance.

// ENTITY
public class Result {
    public String name;
    public int value;

    public Result(String name, int value) {
        this.name = name;
        this.value = value;
    }

    public Result() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Result{" +
                "name='" + name + '\'' +
                ", value=" + value +
                '}';
    }
}

Creation of thread with delay and return value

import java.util.concurrent.*;

public class AsyncCallable {

    public Result calculate() throws ExecutionException, InterruptedException {

        int delay = 5000;
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        Callable<Result> callable = () -> {
            this.wait(delay);
            return new Result("Name", 4);
        };

        Future<Result> future = executorService.submit(callable);
        executorService.shutdown();
        return future.get();
    }

}

Calling method:

import java.util.concurrent.ExecutionException;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        AsyncCallable asyncCallable = new AsyncCallable();

        System.out.println(asyncCallable.calculate().toString());


    }
}

2 Answers2

1

Because your ExecutorService only uses a single thread, it should be fine to just call Thread#sleep instead of Object#wait:

Callable<Result> callable = () -> {
    Thread.sleep(5_000);
    return new Result("Name", 4);
};
Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • Thanks for reply, this solution works, anyway it is not doing exactly what I expected. It should not pause whole application (but it is true that in my example it does not matter) – olejnik.tech Apr 18 '18 at 05:26
1

Well, to stick to your case, any call to wait() must be enclosed in a synchronized block (see the method javadoc here). But, I think you should consider using built-in tools, like Scheduled thread pool. Using this, you can do the following :

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Executors;

final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
// Execute a task after 5 seconds
scheduler.schedule(() -> new Result("Name", 4), 5, TimeUnit.SECONDS);
amanin
  • 3,436
  • 13
  • 17
  • 1
    Ok, so I've been down-voted, and apparently, my answer is not sufficient for the question author. Is it possible to get more details about what is wrong with my answer ? This way I could try to improve it. – amanin Apr 17 '18 at 14:35
  • 1
    Well I do not have enough rep for down-vote. Anyway I used your solution with ScheduledExecutorService and it works like a charm! I will vote after I'll get rep. Thank you very much! :-) – olejnik.tech Apr 18 '18 at 05:21