Does testing usage of ExecutorService add value? - java

This is a class with the only purpose of calling a method from another class but with the addition of timing out after five minutes. With the other class already covered by unit tests, will creating a test for this method have any value other than increasing the test coverage percentage? It seems that the only thing to test would be verifying ExecutorService is functioning as expected though that seems unnecessary as it is a member of java.util.concurrent.
public class FileListRetriever {
private final SshClientFactory sshClientFactory;
public FileRetriever(SshClientFactory sshClientFactory) {
this.sshClientFactory = sshClientFactory;
}
public String getRemoteFiles(String serverIp, Set<String> directories)
throws ExecutionException, TimeoutException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try (SshClient client = sshClientFactory.newClient(serverIp)) {
Future<String> future = executor.submit(() -> client.retrieveFiles(directories));
return future.get(5, TimeUnit.MINUTES);
} finally {
executor.shutdown();
}
}
}

Related

How to execute a service on backgroud and check its status

I'm executing a heavy calculation on the server. The execution is launched from the front and the front is checking the status of the execution each 3 sec.
So I wrote a service like the following :
public class SomeService {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Future<?> noop = CompletableFuture.completedFuture(null);
private final AtomicReference<Future<?>> currentExecution = new AtomicReference<>(noop);
public void execute() {
Future<?> execution = executor.submit(() -> {
// do some heavy calculation here
// ...
// ...
currentExecution.set(noop);
});
currentExecution.set(execution);
}
public boolean isRunning() {
return !currentExecution.get().isDone();
}
}
isRunning method is exposed as an api to the front.
I'm wondering if there's bugs here?
Maybe there's another elegant solution for this requirement?
A simple flag, set when the computation completes, would suffice, as long as it's volatile.
private volatile boolean done;
public void execute() {
executor.submit(() -> {
/* Do some heavy calculation here. */
done = true;
});
}
public boolean isDone() {
return done;
}

Task execution in Java web application

I'm developing Spring MVC web application. One of it's functionalities is file converting (uploading file -> converting -> storing on server).
Some files could be too big for converting on-the-fly so I decided to put them in shared queue after upload.
Files will be converted with priority based on upload time, i.e. FIFO.
My idea is to add task to queue in controller after upload.
There would also be service executing all tasks in queue, and if empty, then wait until new task is added. I don't need scheduling - tasks should be executing always when queue is not empty.
I've read about ExecutorService but I didn't find any example that fit to my case.
I'd appreciate any suggestions.
EDIT
Thanks for answers, I need to clarify my problem:
Basically, I know how to execute tasks, I need to manage with handling the queue of tasks. User should be able to view the queue and pause, resume or remove task from queue.
My task class:
public class ConvertTask implements Callable<String> {
private Converter converter;
private File source;
private File target;
private State state;
private User user;
public ConvertTask(Converter converter, File source, File target, User user) {
this.converter = converter;
this.source = source;
this.target = target;
this.user = user;
this.state = State.READY;
}
#Override
public String call() throws Exception {
if (this.state == State.READY) {
BaseConverterService converterService = ConverterUtils.getConverterService(this.converter);
converterService.convert(this.source, this.target);
MailSendServiceUtil.send(user.getEmail(), target.getName());
return "success";
}
return "task not ready";
}
}
I also created class responsible for managing queue/tasks followed by your suggestions:
#Component
public class MyExecutorService {
private LinkedBlockingQueue<ConvertTask> converterQueue = new LinkedBlockingQueue<>();
private ExecutorService executorService = Executors.newSingleThreadExecutor();
public void add(ConvertTask task) throws InterruptedException {
converterQueue.put(task);
}
public void execute() throws InterruptedException, ExecutionException {
while (!converterQueue.isEmpty()) {
ConvertTask task = converterQueue.peek();
Future<String> statusFuture = executorService.submit(task);
String status = statusFuture.get();
converterQueue.take();
}
}
}
My point is, how to execute tasks if queue is not empty and resume when new task is added and queue was previously empty. I think of some code that fits in add(ConvertTask task) method.
Edited after question updates
You don't need to create any queue for the tasks since the ThreadPoolExecutor implementation has its own queue. Here's the source code of Oracle's Java 8 implementation of newSingleThreadExecutor() method:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
So you just submit a new task directly and it's getting queued by the ThreadPoolExecutor
#Component
public class MyExecutorService {
private ExecutorService executorService = Executors.newSingleThreadExecutor();
public void add(ConvertTask task) throws InterruptedException {
Future<String> statusFuture = executorService.submit(task);
}
}
If you're worried about the bounds of your queue, you can create a queue instance explicitly and supply it to a ThreadPoolExecutor constructor.
private executorService = new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(MAX_SIZE));
Please note that I have removed the line
String status = statusFuture.get();
because get() call is blocking. If you have this line in the same thread where you submit, your code is not asynchronous anymore. You should store the Future objects and check them asynchronously in a different thread. Or you can consider using CompletableFuture introduced in Java 8. Check out this post.
After upload you should return response immediately. The client can't wait for resource too long. However you can change it in the client settings. Anyway if you are running a background task you can do it without interacting with the client or notify the client while execution is in progress. This is an example of callable demo used by the executor service
/**
* Created by Roma on 17.02.2015.
*/
class SumTask implements Callable<Integer> {
private int num = 0;
public SumTask(int num){
this.num = num;
}
#Override
public Integer call() throws Exception {
int result = 0;
for(int i=1;i<=num;i++){
result+=i;
}
return result;
}
}
public class CallableDemo {
Integer result;
Integer num;
public Integer getNumValue() {
return 123;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
ExecutorService service = Executors.newSingleThreadExecutor();
public String execute() {
try{
Future<Integer> future = service.submit(new SumTask(num));
result = future.get();
//System.out.println(result);
service.shutdown();
}
catch(Exception e)
{
e.printStackTrace();
}
return "showlinks";
}
}

Using a shared ExecutorService as a task queue, how do I know when a job is complete?

I have a JobService that processes larger jobs. Jobs are dynamically subdivided into multiple tasks, tasks also might generate sub-tasks, etc, so its not possible to predict the total number of tasks for a job. Each task queues itself to run via ExecutorService.submit(...) The problem is it seems like I have to create a separate ExecutorService for each job, since the only way to tell when the 'job queue' is complete is to use ExecutorService.awaitTermination(...). This seems inefficient though, because I can't share a single threadpool between the jobs and their ExecutorService.
I'm looking for some alternatives, I was thinking of using an AtomicInteger for each job. Incrementing it when I submit a new task, decrementing it when a task finishes. But then I have to poll for when it is zero, and that seems messy, as well as some exception handling mess.
It seems like there must be a better solution?
Submit returns a Future object that can be used to wait on completion of tasks. You could keep track of these and add a method that recursively blocks until all subtasks are done. This way you can reuse the executor wherever you need to.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
public class JobExecutor {
ExecutorService executorService = Executors.newFixedThreadPool(1);
private class Task implements Runnable {
private final String name;
private final Task[] subtasks;
private final ExecutorService executorService;
private volatile boolean started = false;
private Future<?> taskFuture;
// Separate list from subtasks because this is what you'll probably
// actually use as you may not be passing subtasks as constructor args
private final List<Task> subtasksToWaitOn = new ArrayList<Task>();
public Task(String name, ExecutorService executorService,
Task... subtasks) {
this.name = name;
this.executorService = executorService;
this.subtasks = subtasks;
}
public synchronized void start() {
if (!started) {
started = true;
taskFuture = executorService.submit(this);
}
}
public synchronized void blockTillDone() {
if (started) {
try {
taskFuture.get();
} catch (InterruptedException e) {
// TODO Handle
} catch (ExecutionException e) {
// TODO Handle
}
for (Task subtaskToWaitOn : subtasksToWaitOn) {
subtaskToWaitOn.blockTillDone();
}
} else {
// TODO throw exception
}
}
#Override
public void run() {
for (Task subtask : subtasks) {
subtask.start();
subtasksToWaitOn.add(subtask);
}
System.out.println("My name is: " + name);
}
}
void testSubmit() {
Task subsubTask1 = new Task("Subsubtask1", executorService);
Task subtask1 = new Task("Subtask1", executorService, subsubTask1);
Task subtask2 = new Task("Subtask2", executorService);
Task subtask3 = new Task("Subtask3", executorService);
Task job = new Task("Job", executorService, subtask1, subtask2,
subtask3);
job.start();
job.blockTillDone();
System.out.println("Job done!");
}
public static void main(String[] args) {
new JobExecutor().testSubmit();
}
}
Prints out:
My name is: Job
My name is: Subtask1
My name is: Subtask2
My name is: Subtask3
My name is: Subsubtask1
Job done!
If you're on java7 (or java6 with the backport library http://www.cs.washington.edu/homes/djg/teachingMaterials/grossmanSPAC_forkJoinFramework.html ), you might want to consider a Fork-Join pool for this sort of thing:
class MainTask extends RecursiveTask<Long> {
#Override
protected Long compute() {
SubTask subtask0 = new SubTask(0L);
SubTask subtask1 = new SubTask(1L);
SubTask subtask2 = new SubTask(2L);
SubTask subtask3 = new SubTask(3L);
SubTask subtask4 = new SubTask(4L);
SubTask subtask5 = new SubTask(5L);
subtask1.fork();
subtask2.fork();
subtask3.fork();
subtask4.fork();
subtask5.fork();
return subtask0.compute() +
subtask1.join() +
subtask2.join() +
subtask3.join() +
subtask4.join() +
subtask5.join();
}
}
class SubTask extends RecursiveTask<Long> {
private Long rawResult = null;
private Long expected = null;
public SubTask(long expected) {
this.expected = expected;
}
#Override
protected Long compute() {
return expected;
}
}
public static void main( String[] args )
{
ForkJoinPool forkJoinPool = new ForkJoinPool();
Long result = forkJoinPool.invoke(new MainTask());
System.out.println(result);
}
obviously this has hardcoded subtasks, but there's no reason you can't pass parameters to your main task, and use that to generate subtasks. The subtasks themselves don't all have to be of the same type, but they should all extend RecursiveTask. Realistically if a task generates subtasks (like MainTask above), at least one of the subtasks should have "compute" called directly on it (rather and a fork and a join), so that the current thread can execute some computations, and let other threads do the rest.

Wrapping ExecutorService to provide custom execution

I want to write a reusable piece of code to allow waiting conditions while submitting tasks to an executor service. There are alot of implementaions for neat ways of blocking if too many tasks are queue, e.g. here
I need a executor that evaluates all waiting threads, every time on task is finished. For deciding if task is allowed to be submitted atm, the current state of all active tasks must be considered. I came up with the following solution, which doesn't have to scale for multiple submitters or a high grade of simultaneous executed tasks.
Question: Is the following code safe to use, or is there some flaw that I'm missing? The person implementing the aquireAccess method of the ConditionEvaluator<T> must ensure that the way the state of the threads in queried is thread safe, but the implementer needn't safeguard the iteration over the activeTasks collection. Here is the code:
public class BlockingExecutor<T extends Runnable> {
private final Executor executor;
private final ConditionEvaluator<T> evaluator;
final ReentrantLock lock = new ReentrantLock();
final Condition condition = this.lock.newCondition();
final LinkedList<T> active = new LinkedList<T>();
private final long reevaluateTime;
private final TimeUnit reevaluateTimeUnit;
public BlockingExecutor(Executor executor, ConditionEvaluator<T> evaluator) {
this.evaluator = evaluator;
this.executor = executor;
this.reevaluateTimeUnit = null;
this.reevaluateTime = 0;
}
public BlockingExecutor(Executor executor, ConditionEvaluator<T> evaluator, long reevaluateTime, TimeUnit reevaluateTimeUnit) {
this.evaluator = evaluator;
this.executor = executor;
this.reevaluateTime = reevaluateTime;
this.reevaluateTimeUnit = reevaluateTimeUnit;
}
public void submitTask(final T task) throws InterruptedException {
this.lock.lock();
try {
do{
if (this.reevaluateTimeUnit == null) {
this.condition.await(this.reevaluateTime, this.reevaluateTimeUnit);
} else {
this.condition.await();
}
}while(!this.evaluator.aquireAccess(this.active, task));
this.active.add(task);
this.executor.execute(new Runnable() {
#Override
public void run() {
try {
task.run();
} finally {
BlockingExecutor.this.lock.lock();
try{
BlockingExecutor.this.active.remove(task);
BlockingExecutor.this.condition.signalAll();
}finally{
BlockingExecutor.this.lock.unlock();
}
}
}
});
} finally {
this.lock.unlock();
}
}
}
public interface ConditionEvaluator<T extends Runnable> {
public boolean aquireAccess(Collection<T> activeList,T task);
}
Question: Can the code be improved?

How to submit a Callable to an ExecutorService from a thread

I have an application which creates a new thread on a socket connection. I would like to submit a Callable from this thread to an ExecutorService. The Callable needs to execute a program via a command line argument, so I don't want to do this via the connection thread.
The problem is, I don't know how to submit the Callable to an ExecutorService which has a set thread count.
I had considered doing this with a singleton and writing a submit method to submit my Callable to the ExecutorService instance but being unfamiliar with the api, I wasn't sure if this was sensible.
Any help is greatly appreciated,
Thanks.
I would try
static final ExecutorService service = Executors.newFixedThreadPool(4);
Callable call =
service.submit(call);
Here is some code I find online about your problem :
public class CallableExample {
public static class WordLengthCallable
implements Callable {
private String word;
public WordLengthCallable(String word) {
this.word = word;
}
public Integer call() {
return Integer.valueOf(word.length());
}
}
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<Integer>> set = new HashSet<Future≶Integer>>();
for (String word: args) {
Callable<Integer> callable = new WordLengthCallable(word);
Future<Integer> future = pool.submit(callable);
set.add(future);
}
int sum = 0;
for (Future<Integer> future : set) {
sum += future.get();
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
}
There is method submit():
ExecutorService service = Executors.(get the one here you like most)();
Callable<Something> callable = (your Callable here);
Future<AnotherSomething> result = service.submit(callable);
Please note than when using executor service, you have no control over when the task actually starts.

Categories

Resources