ExecutorService with Runnable share CyclicBarrier - java

I have a problem in a concurrent solution in Java using n Runnable class that share a CyclicBarrier, and the Runnable are handled by a ExecutorService, this is the code:
public class Worker implements Runnable {
private CyclicBarrier writeBarrier;
private int index;
private int valuetocalculate;
public Worker(int i,CyclicBarrier writeBarrier)
{
this.writeBarrier = writeBarrier;
this.index = i;
this.valuetocalculate = 0;
}
public void run() {
//calculations with valuetocalculate
writeBarrier.await();
//write new valuetocalculate value
}
}
public class Context {
private ArrayList<Worker> workers;
private Chief chief;
public Context()
{
workers = new ArrayList<Worker>();
chief = new Chief();
}
public void generateRandomWorkers(nworkers)
{
writeBarrier = newWriteBarrier(workers);
chief.setBarrier(writeBarrier);
//generate random woker
for (int i = 0; i<nworkers;i++)
{
Worker worker = new Worker(i,writeBarrier);
workers.add(worker);
}
chief.setWorkersArray(workers);
chief.start();
}
}
public class Chief extend Thread {
private CyclicBarrier writeBarrier;
private ArrayList<Worker> workers;
private ExecutorService executor;
private int cores;
public Chief ()
{
cores = Runtime.getRuntime().availableProcessors()+1;
}
public void setBarrier (CyclicBarrier writeBarrier)
{
this.writeBarrier = writeBarrier;
}
public setWorkersArray(ArrayList<Worker> workers)
{
this.workers = workers;
}
public ArrayList<Integer> getvaluetocalculate()
{
ArrayList<Integer> values = new ArrayList<Integer> ();
for (int i = 0; i<workers.size();i++)
{
values.add(workers.get(i).valuetocalculate);
}
return values;
}
public void run(){
while (!stop) //always true for testing
{
getvaluetocalculate();
//make calculations
writeBarrier.reset();
executor = Executors.newFixedThreadPool(cores);
for (int i = 0;i<workers.size();i++)
{
Runnable runnable = workers.get(i);
executor.execute(runnable);
}
executor.shutdown();
while (!executor.isTerminated())
{
}
}
}
}
All start in the main with:
Context = new Context();
context.generateRandomWorkers();
The problem is that the Runnable doesn't go over the first "iteration" in the run of the Chief, so seems that the problem is that the Workers doesn't go over the writerBarrier.await();, instead if I initialized this:
executor = Executors.newFixedThreadPool(cores);
with the workers.size(), works but seems not synchronized...how I can solve?

OK so it looks like you are trying to do the following
One chief/scheduler which controls the workers
One or more workers doing calculations
Chief executes all workers
Chief waits for all workers to complete
Chief gets results from each Worker to calculate result
Assuming the above here are your problems.
Doing the barrier.await() in the worker run() method prevents that thread from being released back to the pool to run subsequent workers. Therefore the when pool size < worker size the first 'pool size' workers consume the threads and then stop waiting for the others which can't run. This is why not all your workers run unless you change the pool size to workers.size().
The valuetocalculate variable is not synchronised between the worker setting the result and the chief reading it so you might be seeing stale results.
The correct way to implement this sort of system is to have the workers implement Callable where the callable returns the result once the worker has calculated. This takes care of publishing the results back to your chief (you'll see below how this works).
Remove the cyclic barrier, you don't need that.
Create the executor as you are now and call invokeAll() with a list of Callables (your workers). This method invokes the Callables using the executor and waits for them to complete. It blocks until all workers have completed at which point it will return a List<Future<T>>. Each Future corresponds to one of the workers/Callables you passed in. Iterate the list pulling the results out. If a worker has failed trying to get() the result from it's Future will throw an exception.
Hope that helps.

Related

spring boot and Executor Service

I am using spring boot
public interface StringConsume extends Consumer<String> {
default public void strHandel(String str) {
accept(str);
}
}
Impl
#Component("StrImpl")
public class StringConsumeImpl implements StringConsume {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(500);
final ExecutorService exService = Executors.newSingleThreadExecutor();
Future<?> future = CompletableFuture.completedFuture(true);
#Override
public void accept(String t) {
try {
queue.put(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (null != queue.peek()) {
if (future.isDone()) {
future = exService.submit(() -> queue.take());
}
}
}
}
Class
#Component
public class Test {
#Resource(name="StrImpl")
private #Autowired StringConsume handler;
public void insertIntoQueue(String str) {
handler.accept(str);
}
}
In StringConsumeImpl , do I need synchronized while loop? and suppose five time StringConsumeImpl class called, then do while loop will create 5 process or only 1 process ? and what is the best replacement of while loop in StringConsumeImpl , if any ?
There are some problems with that code.
First of all, the consumer doesn't really "consume" anything, it just adds the string to the queue then takes it back out. Let's say for the sake of the argument that it also "consumes" it by printing it to console or something.
Secondly, the consumer will only get called once due to the loop unless it is running in a thread of its own. Eg if you do
public static void main(String[]args) {
StringConsume consumer = new StringConsumeImpl();
consumer.accept("hello");
}
The consumer will put "hello" into the queue, take it out immediately and then stay in the loop, waiting for more elements to take out; however, no one is there to actually add any.
The usual concept of doing what it looks like you're trying to do is "producer/consumer". This means that there is a "producer" that puts items into a queue and a "consumer" taking them out and doing stuff with them.
So in your case what your class does is "consume" the string by putting it into the queue, making it a "producer", then "consuming" the string by taking it back out of the queue. Of course, there's also the "actual" producer of the string, ie the class calling this.
So in general you'd do something like this:
/** Produces random Strings */
class RandomStringProducer {
Random random = new Random();
public String produceString() {
return Double.toString(random.nextDouble());
}
}
/** Prints a String */
class PrintConsumer implements StringConsume {
public void accept(String s) { System.out.println(s); }
}
/** Consumes String by putting it into a queue */
class QueueProducer implements StringConsume {
BlockingQueue<String> queue;
public QueueProducer(BlockingQueue<String> q) { queue = q; }
public void accept(String s) {
queue.put(s);
}
}
public static void main(String[] args) {
// the producer
RandomStringProducer producer = new RandomStringProducer();
// the end consumer
StringConsume printConsumer = new PrintConsumer();
// the queue that links producer and consumer
BlockingQueue<String> queue = new ArrayBlockingQueue<>();
// the consumer putting strings into the queue
QueueProducer queuePutter = new QueueProducer(queue);
// now, let's tie them together
// one thread to produce strings and put them into the queue
ScheduledExecutorService producerService = Executors.newScheduledThreadPool(1);
Runnable createStringAndPutIntoQueue = () -> {
String created = producer.createString();
queuePutter.consume(created);
};
// put string into queue every 100ms
producerService.scheduleAtFixedRate(createStringAndPutIntoQueue, 100, TimeUnit.MILLISECONDS);
// one thread to consume strings
Runnable takeStringFromQueueAndPrint = () -> {
while(true) {
String takenFromQueue = queue.take(); // this will block until a string is available
printConsumer.consume(takenFromQueue);
}
};
// let it run in a different thread
ExecutorService consumerService = Executors.newSingleThreadExecutor();
consumerService.submit(takeStringFromQueueAndPrint);
// this will be printed; we are in the main thread and code is still being executed
System.out.println("the produce/consume has started");
}
So when you run this, there will be three threads: the main thread, the producer thread and the consumer thread. The producer and consumer will be doing their thing concurrently, and the main thread will also continue to run (as exemplified by the System.out.println in the last line).

User Created Thread Pool Shutdown having different behaviour when a sysout is added

I was asked to create my own thread pool in an interview where I have to create the number of threads requested by the user. Allow user to submit there task and finally shutdown the pool. I wrote the below program which is working fine in all the cases other than shutdown.
public class ThreadPool
{
public final Queue<Runnable> workerQueue;
private static boolean isrunning = true;
private Thread[] workerThreads;
public ThreadPool(int N)
{
workerQueue = new LinkedList<>();
workerThreads = new Thread[N];
for (int i = 0; i < N; i++) {
workerThreads[i] = new Worker("Pool Thread " + i);
workerThreads[i].start();
}
}
public void shutdown()
{
while(isrunning){
if(workerQueue.isEmpty()){
isrunning = false;
}
}
}
public void submit(Runnable r) throws Exception
{
workerQueue.add(r);
}
private class Worker extends Thread
{
public Worker(String name)
{
super(name);
}
public void run()
{
while (isrunning) {
try {
if(!workerQueue.isEmpty())
{
Runnable r = workerQueue.poll();
r.run();
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}
}
The Test method I wrote is like below
static public void main(String[] args) throws Exception
{
ClassA a1 = new ClassA();
ClassA a2 = new ClassA();
ClassA a3 = new ClassA();
ClassA a4 = new ClassA();
ClassA a5 = new ClassA();
ClassA a6 = new ClassA();
ThreadPool tp = new ThreadPool(5);
tp.submit(a1);
tp.submit(a2);
tp.submit(a3);
tp.submit(a4);
tp.submit(a5);
///////////////
tp.submit(a6);
tp.shutdown();
}
But the program is never ending, its running always and I have to stop it manually in eclipse. But if I add a simple System.out.print("") in my method shutdown, its working perfrectly(the Program is ended after the execution of all the threads).
Can you please tell me why its working with the sysout and why its not working with out it ?
You have two major problems with your code:
You are using an implementation of Queue that's not synchronized in a multithread environment. This leads to a Race Condition when multiple threads insert/remove from the queue. Please consider using something like:
workerQueue = new ConcurrentLinkedQueue()
You run some very tight loops, one in your Worker.run() method where you're not checking for NPE and not allowing for some "cooldown", and another one in shutdown():
while (isrunning) {
...
Runnable r = workerQueue.poll();
r.run();
...
}
This, coupled with 1, leads to the Queue being emptied without properly updating the size info: ie. isEmpty() returns false but poll() returns null. Your program will become stuck in a loop. This doesn't happen when you add System.out.print() due to different timing specific to your configuration (it can continue to fail in other environments - especially where there are more than 6 cpu cores available).

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