I have two concurrent threads (producer and consumer), and two queues (pending and execution).
This is a sample flow for producer:
"1" - If not duplicate (does not exist in any of queues), push task T1
"3" - If not duplicate (does not exist in any of queues), push task T1
And this is a sample flow for consumer:
"2" - Poll data from "pending" queue
"4" - If found something, push it into "execution" queue and run it in a separate thread.
Notice the numbering above:
If between steps 2 and 4, step 3 happens, it can insert a duplicate because the data is still in-memory and is not pushed into "execution" queue yet.
How can I prevent this? I can not put a lock on both queues because then the "consumer" thread will always keep the lock (it is an always running thread polling for data).
P.S.
This is how my consumer looks like:
while ( true ) {
var nextTask = pending.poll(100, MILLISECOND); //STEP 2
if ( nextTask != null ) {
executeQueue.add(nextTask); //STEP 4
executeInParallel(nextTask);
}
}
This might not be a direct answer to your question. But if you are looking for a solution to queue tasks to process them with a number of threads you should have a look at the Executors from Java.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JobQueue {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
executorService.submit(() -> {
// do someting
return "result";
});
}
}
Update: check queue:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class JobQueue {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
Runnable task = () -> {
// do someting
};
BlockingQueue<Runnable> queue = executorService.getQueue();
if(!queue.contains(task)) {
executorService.submit(task);
}
}
}
You can synchromize on an Object uning wait() and notify()
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
public class JobQueue {
private static final Object syncMon = new Object();
private static final Queue<Object> pending = new ArrayDeque<>();
private static final Set<Object> executing = new HashSet<>();
public void produce(Object o) {
synchronized (syncMon) {
if(pending.contains(o) || executing.contains(o))
return;
pending.add(o);
syncMon.notifyAll();
}
}
public Object consume() throws InterruptedException {
synchronized (syncMon) {
if(pending.isEmpty())
syncMon.wait();
Object task = pending.poll();
if(task != null) {
executing.add(task);
}
return task;
}
}
public void complete(Object task) {
synchronized (syncMon) {
executing.remove(task);
}
}
}
The syncMon object is not necesarry. You could also use wait() and notify() on the Queue directly.
like pending.notifyAll();
To explain this a litte: If you invoke wait() in a synchronized block the lock is released. So the producer can enter the synchronized while the consumer is waiting. If you call notify() or notifyAll() the waiting thread wakes up and takes the lock back, once the producer has exited the synchronized block.
Update 1: add execution set.
Related
So I'm making an emulator for an online game and I can't seem to think of a good way to deal with lots of tasks running simultaneously. Loading everything on a single thread just doesn't work, obviously.
My idea was to have a main thread that delegates tasks to x amount of worker threads. Once the main thread is done queueing tasks, it signals the workers to start firing tasks and halts untill they have finished. My implementation is as follows:
package com.rs2.engine;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
import java.util.ArrayList;
import com.rs2.util.Timer;
public class Engine implements Runnable {
private ScheduledExecutorService scheduledExecutorService;
private ExecutorService executorService;
private int currentTick;
private ArrayList<Task> tasks;
private Timer timer;
public Engine(int workers) {
this.executorService = Executors.newFixedThreadPool(workers);
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
this.currentTick = 0;
this.tasks = new ArrayList<>(10000);
this.timer = new Timer();
}
public int getCurrentTick() {
return currentTick;
}
public ExecutorService getWorkers() {
return executorService;
}
public void start() {
this.scheduledExecutorService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
public void cycle() {
}
public void queueTask(Task task) {
tasks.add(task);
}
public void processQueuedTasks() {
try {
CountDownLatch latch = new CountDownLatch(tasks.size());
for (int i = 0; i < tasks.size(); i++) {
Task t = tasks.get(i);
t.setCountDownLatch(latch);
executorService.submit(t);
}
latch.await();
tasks.clear();
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
timer.reset();
cycle();
currentTick++;
//System.out.println("Cycle time: "+timer.elapsed());
}
}
queueTask() and processQueuedTasks() are only called from the main thread. This Engine is used to deal with any and all tasks that the server needs executing. First it processes networking events (incoming packets), then updating entities and other events. That's why I like to keep it abstract.
Here's the Task class aswell:
package com.rs2.engine;
import java.util.concurrent.CountDownLatch;
public class Task implements Runnable {
private CountDownLatch latch;
public Task() {
}
#Override
public void run() {
execute();
latch.countDown();
}
public void execute() {
}
public void setCountDownLatch(CountDownLatch latch) {
this.latch = latch;
}
}
My questions are as follows:
In the Engine class, is it OK to work with a regular ArrayList in terms of concurrency?
Is there a better way of queueing tasks to the ExecutorService? I feel like it might cause issues if too many tasks are queued to it at the same time.
Are there any engine frameworks I should be looking at before I start reinventing the wheel?
If you are worried that you might be queueing too much tasks in the ExecutorService you can use Semaphore to limit the tasks it can run at a time.
Put it in your processQueuedTasks() method for loop to limit the number of tasks to be run.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html
Instead of using a Semaphore to throttle the number of tasks run concurrently, you could set the number of threads in the threadpool. You will only get as many tasks running concurrently as you have threads
Executors.newFixedThreadPool(n);
public void queueTask(Task task) {
As this method is public, it can be called from any thread and so the ArrayList would not be thread safe. Think about what would happen if you tried to queue a task during the time they are submitted to the executor. You have 'borrowed' functionality from a thread pool executor and placed it in your code by having the collection for tasks.
I've two threads Producer and Consumer. In objective-c language I've used semaphores to block and release thread Consumer.
Note: This is related to Producer-Consumer Problem But not fully. Here Producer will not wait for consumer to consume. But consumer will wait till Producer produces. Here Consumer is not continuously reading. He's reading Only when Producer tells him to read. And reads only some data. And here its not about shared memory kinda.
Thread Consumer{
while(true) {
//Consumer is waiting
dispatch_semaphore_wait(semaphoreVariable, DISPATCH_TIME_FOREVER);
//Copies the data and then goes to wait.
}
}
Thread Producer{
while(true){
//write to buffer
//Continuously writes to buffer. No Waiting.
//After writing Some Blocks asks consumer to consume
dispatch_semaphore_signal(semaPhoreBlock);
}
}
Like this the semaphore is used to continuously block and release Consumer Thread.
How to achieve this kind of mechanism in JAVA? Any kind of help is greatly appreciated.
I would solve this coordination problem with a "barrier".
The consumer won't read continuously. It only reads a batch of work when the producer notifies him to do so (by reseting the barrier).
I added some waiting for the producer too (so the queue won't overflow if the consumer is too slow), but the producer will only wait if after producing a batch of work, there is no consumer ready to consume it.
see below:
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class BarrierExample {
public static final int BATCH_SIZE = 10;
public static void main(String[] args) throws InterruptedException {
BarrierExample barrierExample = new BarrierExample();
barrierExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
Queue<String> queue = new ConcurrentLinkedQueue();
CyclicBarrier barrier = new CyclicBarrier(2);
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Producer(BATCH_SIZE, queue, barrier));
executorService.submit(new Consumer(BATCH_SIZE, queue, barrier));
Thread.sleep(4000);
System.out.println("main program: trying to shutdown executor service");
executorService.shutdownNow();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
class Producer implements Callable<Void> {
private final int batchSize;
private Queue queue;
private CyclicBarrier barrier;
private Random random = new Random();
public Producer(int batchSize, Queue queue, CyclicBarrier barrier) {
this.batchSize = batchSize;
this.queue = queue;
this.barrier = barrier;
}
#Override
public Void call() {
while (true) {
IntStream.range(1, batchSize).forEach(i -> queue.add(String.valueOf(random.ints(1, 10).findFirst().getAsInt())));
System.out.println("producer: batch size was added to queue.");
while (barrier.getNumberWaiting() < 1) {
try {
System.out.println("producer: nobody is waiting on barrier. going to sleep now");
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
System.out.println("producer: consumer was waiting on barrier. reseting the barrier now");
barrier.reset();
if (Thread.currentThread().isInterrupted()) {
System.out.println("producer is ending now!");
break;
}
}
return null;
}
}
class Consumer implements Callable<Void> {
private final int batchSize;
private Queue queue;
private CyclicBarrier barrier;
public Consumer(int batchSize, Queue queue, CyclicBarrier barrier) {
this.batchSize = batchSize;
this.queue = queue;
this.barrier = barrier;
}
#Override
public Void call() {
while (true) {
boolean barrierIsBroken = false;
try {
System.out.println("consumer: waiting on barrier");
barrier.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (BrokenBarrierException e) {
System.out.println("consumer: barrier is broken!!");
barrierIsBroken = true;
}
if (barrierIsBroken) {
System.out.println("consumer: consuming batch");
IntStream.range(1, batchSize).forEach(i -> System.out.println(queue.remove()));
System.out.println("consumer: queue size:" + queue.size());
}
try {
System.out.println("consumer: going to sleep");
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (Thread.currentThread().isInterrupted()) {
System.out.println("consumer is ending now!");
break;
}
}
return null;
}
}
The Java solution is: don't go for "low level" concepts such a using/implemeenting semaphores.
Instead, use one of the many abstractions that the Java platform is offering, for example the LinkedBlockingQueue.
It is pretty simple: when you got two threads, one thread pushes content into the queue; and the the other reader thread uses the take() method in order to fetch content.
Where: take() blocks! Therefore you don't need to worry at all about sending signals "manually". One thread writes, the reader sits and waits until content becomes available. Meaning: you do not need to tell the reader explicitly "start reading" - that happens implicitly, under the covers.
In that sense: the real answer is to study the offerings that Java has to make, instead of trying to build abstractions yourself. A good starting point are the Oracle tutorials on concurrency. Don't assume that your solution from language A must "work" the same way in another language. In Java, the writer does not need to signal the reader when using a BlockingQueue. So don't make your life more complicated by enforcing a concept that comes from another language!
I have problem using Executorservice
I implemented Consumer-Producer Pattern
Main
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
Thread producer = new Thread(new Producer(queue));
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable consumer1 = new Consumer(queue);
Runnable consumer2 = new Consumer(queue);
Runnable consumer3 = new Consumer(queue);
producer.start();
executorService.submit(consumer1);
executorService.submit(consumer2);
executorService.submit(consumer3);
executorService.shutdown();
}
}
Producer
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable{
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public synchronized void run() {
for (int i=0; i<100; ++i) {
try {
//System.out.println("i = " + i);
queue.put(i);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
Consumer
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
while (true) {
try {
//queue.take(); // case 1
System.out.println(Thread.currentThread().getName() + " Consumer : " + queue.take()); // case 2
} catch (InterruptedException e) {
System.out.println(e);
}
if (queue.isEmpty()) {
break;
}
}
}
}
I wonder why (Consumer.java) case 1 is not working,
but case 2 is fine
It print noting and never stopping (This comment isn't good. Ignore it ㅠㅠ)
I just wonder, Why case 1 is not Stop.
Is there something in System.out.println or BlockingQueue?
(Poducer.java also. If i added print i in Producer.java then Throws InterruptedException)
May be I don't know java and thread well.
Please help me ;(
(My English isn't good, Sorry)
The fundamental problem here is that if the queue ever becomes empty just before the queue.take(), the consumer thread will block until something gets added to the queue. Since you do all the adding to the queue prior to starting the consumers, it is a matter of luck whether one of the consumers will get into a blocked state.
It appears that case 2 (with the console output) slows things down enough that no thread gets into this state. In case 1 processing is so fast that at least one thread finds itself blocked. When I ran your code I found thread 3 blocked, meaning that probably threads 1 and 2 consumed all entries in the queue before thread 3 even had a chance to get started.
If your usecase involves the queue being filled first by the Producer and then running the Consumer threads, you should use poll() instead of take() which will let you detect the condition of running out of elements.
The title pretty much sums it.
I want to know the concept and idea of callable . I have read a question here on difference between callable and runnable. but no one show code and give detail what a callable is. I don't want to know the difference between them. I want to know ,
What is a callable ?
When to use them and how to use them .
When they come in action for
Android.
You can check this example:
In this example Callable task returns the name of thread executing the task after one second. We are using Executor framework to execute 100 tasks in parallel and use Future to get the result of the submitted tasks.
package com.journaldev.threads;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MyCallable implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(1000);
//return the thread name executing this callable task
return Thread.currentThread().getName();
}
public static void main(String args[]){
//Get ExecutorService from Executors utility class, thread pool size is 10
ExecutorService executor = Executors.newFixedThreadPool(10);
//create a list to hold the Future object associated with Callable
List<Future<String>> list = new ArrayList<Future<String>>();
//Create MyCallable instance
Callable<String> callable = new MyCallable();
for(int i=0; i< 100; i++){
//submit Callable tasks to be executed by thread pool
Future<String> future = executor.submit(callable);
//add Future to the list, we can get return value using Future
list.add(future);
}
for(Future<String> fut : list){
try {
//print the return value of Future, notice the output delay in console
// because Future.get() waits for task to get completed
System.out.println(new Date()+ "::"+fut.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
//shut down the executor service now
executor.shutdown();
}
}
You may also check Using Callable to Return Results From Runnables
Callable is similar to Runnable but it returns a result and may throw an exception.
Use them when you expect your asynchronous tasks to return result.
The returned result of asynchronous computation is represented by a Future.
You can check this simple example implemented using FutureTask (which implements RunnableFuture and Future)
public static void main(String[] args) {
// providing an anonymous callable to FutureTask
RunnableFuture<String> future = new FutureTask<String>(
new Callable<String>() {
#Override
public String call() throws InterruptedException {
System.out.println("sleeping");
Thread.sleep(2000);
System.out.println("returning");
return "hello-world";
}
});
Thread t = new Thread(future);
t.start();
try {
// the get Waits if necessary for the computation to complete
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
I wrote a producer/consumer based program using Java's BlockingQueue. I'm trying to find a way to stop the consumer if all producers are done. There are multiple producers, but only one consumer.
I found several solutions for the "one producer, many consumers" scenario, e.g. using a "done paket / poison pill" (see this discussion), but my scenario is just the opposite.
Are there any best practice solutions?
The best-practice system is to use a count-down latch. Whether this works for you is more interesting.....
Perhaps each producer should register and deregister with the consumer, and when all producers are deregistered (and the queue is empty) then the consumer can terminate too.
Presumably your producers are working in different threads in the same VM, and that they exit when done. I would make another thread that calls join() on all the producers in a loop, and when it exist that loop (because all the producer threads have ended) it then notifies the consumer that it's time to exit. This has to run in another thread because the join() calls will block. Incidentally, rolfl's suggestion of using a count down latch would have the problem, if I understand it correctly.
Alternately, if the producers are Callables, then the consumer can call isDone() and isCanceled() on their Futures in the loop, which won't bock, so it can be used right in the consumer thread.
You could use something like the following, i use registerProducer() and unregisterProducer() for keeping track of the producers. Another possible solution could make use of WeakReferences.
It's worth to mention that this solution will not consume the events that have already been queued when the consumer is shut down, so some events may be lost when shutting down.
You would have to drain the queue if the consumer gets interrupt and then process them.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class TestConsumerShutdown {
private static interface SomeEvent {
String getName();
}
private static class Consumer implements Runnable {
private final BlockingQueue<SomeEvent> queue = new ArrayBlockingQueue<>(10);
private final ExecutorService consumerExecutor = Executors.newSingleThreadExecutor();
private final AtomicBoolean isRunning = new AtomicBoolean();
private final AtomicInteger numberProducers = new AtomicInteger(0);
public void startConsumer() {
consumerExecutor.execute(this);
}
public void stopConsumer() {
consumerExecutor.shutdownNow();
try {
consumerExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void registerProducer() {
numberProducers.incrementAndGet();
}
public void unregisterProducer() {
if (numberProducers.decrementAndGet() < 1) {
stopConsumer();
}
}
public void produceEvent(SomeEvent event) throws InterruptedException {
queue.put(event);
}
#Override
public void run() {
if (isRunning.compareAndSet(false, true)) {
try {
while (!Thread.currentThread().isInterrupted()) {
SomeEvent event = queue.take();
System.out.println(event.getName());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Consumer stopped.");
isRunning.set(false);
}
}
}
}
public static void main(String[] args) {
final Consumer consumer = new Consumer();
consumer.startConsumer();
final Runnable producerRunnable = new Runnable() {
#Override
public void run() {
final String name = Thread.currentThread().getName();
consumer.registerProducer();
try {
for (int i = 0; i < 10; i++) {
consumer.produceEvent(new SomeEvent() {
#Override
public String getName() {
return name;
}
});
}
System.out.println("Produver " + name + " stopped.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
consumer.unregisterProducer();
}
}
};
List<Thread> producers = new ArrayList<>();
producers.add(new Thread(producerRunnable, "producer-1"));
producers.add(new Thread(producerRunnable, "producer-2"));
producers.add(new Thread(producerRunnable, "producer-3"));
for (Thread t : producers) {
t.start();
}
}
}