I'm creating a game and I'm stuck in this problem:
I have the class Game and inside the Game, I have the Kitchen.
When the player type for example: /new egg I do: game.kitchen.newEgg()
I would like to know what is the best way, and how I can notify the game that the Egg is finished.
I tried putting the class Game as static, but is doesn't seem correct.
I also tried every 1 second the game call kitchen.isReady() (neither this looks like correct)
and my last try was create a Consumer like this:
public class Kitchen {
public void newEgg(String name, Consumer<String> function){
System.out.println("egg is in progress");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
function.accept(name);
}
}
and in the game:
public void createEgg(String eggName){
System.out.println("Creating an Egg");
Kitchen egg = new Kitchen();
Gamex x = new Gamex();
Runnable task2 = () -> { egg.newEgg(eggName, x::eggCreated); };
new Thread(task2).start();
System.out.println("game continue...");
}
public void eggCreated(String eggName) {
System.out.println("Egg: " + eggName + " finished.");
}
All the tree methods worked, but Is this the proper way to do?
How I should do it?
What is the best solution for a game?
Being notified that an asynchronous job is done would be a job for a CompletableFuture<V> (Java 8).
It is quite like a Future<V>, only you can attach to it additional callbacks that get triggered immediately when the job completes.
Here is a minimal working example that you could adapt to your game engine :
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Example {
public static void main(String[] args) {
Example example = new Example();
// Start generating a String
ExecutorService pool = Executors.newFixedThreadPool(4); // We need some pool to run things async
CompletableFuture.supplyAsync(example::createString, pool) // run the creation job in another thread
.thenAccept(example::callback); // run this callback when the job is done
pool.shutdown();
// Doing something else in the meantime...
System.out.println("Meandering...");
}
private String createString() {
artificialDelay();
return "Hello World";
}
private void callback(String input) {
System.out.println("Received this : " + input);
}
private void artificialDelay() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Related
Recently I've started looking into multithreading, and I have a question, perhaps more experienced ones could help.
My program creates two parallel threads, each of them prints counts from 0 to 19 (the NumbersPrinter class, which implements the Runnable interface).
class NumbersPrinter implements Runnable {
private Mediator mediator;
private String name;
private int makeActionOnCount;
public NumbersPrinter(Mediator mediator, String name, int makeActionOnCount) {
this.mediator = mediator;
this.name = name;
this.makeActionOnCount = makeActionOnCount;
}
#Override
public void run() {
for(int i = 0; i<20; i++){
try {
synchronized(this.mediator) {
if(this.mediator.actionInProgress.get()) {
System.out.println(name + " waits");
wait();
}
}
System.out.println(this.name + " says " + i);
Thread.sleep(500);
if(i == makeActionOnCount) {
synchronized(this.mediator) {
System.out.println(this.name + " asks Mediator to perform action...");
this.mediator.performAction();
this.mediator.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
When one of the threads reaches a certain number (defined in the makeActionOnCount variable), it starts performing a certain action that stops the execution of the second counter. The action lasts 5 seconds and after that both counters continue to count.
The counters are interconnected through an instance of the Mediator class, the performAcyion() method also belongs to the instance of the Mediator class.
import java.util.concurrent.atomic.AtomicBoolean;
class Mediator {
public AtomicBoolean actionInProgress = new AtomicBoolean(false);
public Mediator() {
}
public void performAction() throws InterruptedException {
actionInProgress.set(true);
System.out.println("Action is being performed");
Thread.sleep(5000);
System.out.println("Action has been performed");
actionInProgress.set(false);
}
}
Here's the Main class:
class Main {
public static void main(String[] args) throws InterruptedException{
Mediator mediator = new Mediator();
NumbersPrinter data = new NumbersPrinter(mediator, "Data", 10);
NumbersPrinter lore = new NumbersPrinter(mediator, "Lore", 5);
Thread oneThread = new Thread(data);
Thread twoThread = new Thread(lore);
System.out.println("Program started");
oneThread.start();
twoThread.start();
oneThread.join();
twoThread.join();
System.out.println("Program ended");
}
The way the program is written now - works fine, but I don't quite understand what exactly should I write in the first synchronized block, because if you delete all content from it, the program still works, since the counter that does not execute the performAction() method stops 'cause the counter cannot access the monitor of the Mediator object 'cause it is busy with the parallel counter. AtomicBoolean variable and checking it also makes no sense.
In other words, I may not use the wait () and notify () constructs at all, as well as the value of the AtomicBoolean variable, and just check access to the Mediator object's monitor every new iteration using an empty synchronized block. But I've heard that an empty synchronized block is a bad practice.
I am asking for help on how to rewrite the program to use the synchronized block and the wait() and notify() methods correctly.
Maybe I'm syncing on the wrong object? How would you solve a similar problem?
Thanks in advance
We are creating a rest application. And we have an edge condition where parallel actions are not supported on same object.
For example :
Not supported in parallel
Request 1 for action XYZ for object A
Request 2 for action XYZ for object A
Request 3 for action ABC for object A
Supported in parallel
Request 1 for action XYZ for object A
Request 2 for action XYZ for object B
Request 3 for action ABC for object C
Now, the object count is not fixed. we can have n number of such objects.
I want that if a request for object A is under progress then other request for object A should wait for existing task on object A to get over.
But I am not able to figure out the algorithm for this purpose.
I could plan for below design but not able to figure out on how to use the locking since all objects can be different.
A queue which stores the entry for object A when request comes.
Entry gets deleted if response is sent
If an entry is already present, then wait for existing request to get over.
If entry not present, then execute immediately.
Now task on object A should not impact the task on object B. So they must accept unique locks.
And also, request cannot go standalone and be queued. Somehow I have to make the current thread sleep so that I can send response to user.
Can anyone guide here?
UPDATED based on comments from my original response
The ideal model for something like that would be using an actor system such as Akka.
But your comment states that this will happen in the context on a REST application where threads will be blocked already by request processing.
In this case, the idea would be using a per-object-guard such as:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
public class ObjectGuard<K> {
private final ConcurrentMap<K, CountDownLatch> activeTasks = new ConcurrentHashMap<>();
public Guard guardFor(final K key) throws InterruptedException {
if (key == null) {
throw new NullPointerException("key cannot be null");
}
final CountDownLatch latch = new CountDownLatch(1);
while (true) {
final CountDownLatch currentOwner = activeTasks.putIfAbsent(key, latch);
if (currentOwner == null) {
break;
} else {
currentOwner.await();
}
}
return () -> {
activeTasks.remove(key);
latch.countDown();
};
}
public interface Guard extends AutoCloseable {
#Override
void close();
}
}
You would use it as follows:
class RequestProcessor {
private final ObjectGuard<String> perObjectGuard = new ObjectGuard<>();
public String process(String objectId, String op) throws InterruptedException {
// Only one thread per object id can be present at any given time
try (ObjectGuard.Guard ignore = perObjectGuard.guardFor(objectId)) {
String result = ... // compute response
}
}
}
If two concurrent calls to process are received for the same object id, only one will be processed, the others wait their turn to process a request on that object.
An object which executes requests serially is known as Actor. The most widely known java actor library is named Akka. The most simple (one page) actor implementation is my SimpleActor.java.
Signalling like juancn does in his answer is not my strong suit, so I made an even cruder solution using one Semaphore for signalling combined with a request-counter.
There is one lock involved (subjectsLock) which synchronizes everything at one point in time. The lock is required to ensure there are no memory leaks: since there can be any number of subjects (a.k.a. object identifiers in your question), cleanup is essential. And cleanup requires knowing when something can be removed and that is difficult to determine without a lock that brings everything to one known state at a certain point in time.
The test in the main-method in the code shown below is a bit hard to read, but it serves as a starting point for a demonstration of how the code works internally. The main logic is in the methods executeRequest, addSubject and removeSubject. If those three methods do not make sense, another solution should be used.
Stress-testing will have to determine if this solution is fast enough: it depends on the number of requests (per second) and the amount of time it takes to complete an action. If there are many requests and the action is short/fast, the (synchronization) overhead from the lock could be to high.
// package so;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;
public class RequestQueue {
public static void main(String[] args) {
// Randomized test for "executeRequest" method below.
final int threadCount = 4;
ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
try {
final int requestCount = 100;
final RequestQueue rq = new RequestQueue();
final Random random = new Random();
IntStream.range(0, requestCount).forEach(i -> threadPool.execute(new Runnable() {
#Override
public void run() {
try {
String subject = "" + (char) (((int)'A') + random.nextInt(threadCount));
rq.executeRequest(subject, new SleepAction(i, subject, 50 + random.nextInt(5)));
} catch (Exception e) {
e.printStackTrace();
}
}
}));
sleep(100); // give threads a chance to start executing.
while (true) {
sleep(200);
List<String> subjects = rq.getSubjects();
System.out.println("Subjects: " + subjects);
if (subjects.isEmpty()) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
private Map<String, QueueLock> subjects = new LinkedHashMap<>();
// a fair ReentrantLock is a little bit slower but ensures everybody gets their turn in orderly fashion.
private final ReentrantLock subjectsLock = new ReentrantLock(true);
private class QueueLock {
// a fair Semaphore ensures all requests are executed in the order they arrived.
final Semaphore turn = new Semaphore(1, true);
final AtomicInteger requests = new AtomicInteger(1);
public String toString() { return "request: " + requests.get(); }
}
/**
* Allow all requests for different subjects to execute in parallel,
* execute actions for the same subject one after another.
* Calling thread runs the action (possibly after waiting a bit when an action for a subject is already in progress).
*/
public String executeRequest(String subject, Runnable action) throws InterruptedException {
QueueLock qlock = addSubject(subject);
try {
int requestsForSubject = qlock.requests.get();
if (requestsForSubject > 1) {
System.out.println(action.toString() + " waiting for turn " + requestsForSubject);
}
qlock.turn.acquire();
if (requestsForSubject > 1) {
System.out.println(action.toString() + " taking turn " + qlock.requests.get());
}
action.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
removeSubject(subject);
}
return timeSinceStart() + " " + subject;
}
private QueueLock addSubject(String s) {
QueueLock qlock = null;
subjectsLock.lock();
try {
qlock = subjects.get(s);
if (qlock == null) {
qlock = new QueueLock();
subjects.put(s, qlock);
} else {
qlock.requests.incrementAndGet();
}
} finally {
subjectsLock.unlock();
}
return qlock;
}
private boolean removeSubject(String s) {
boolean removed = false;
subjectsLock.lock();
try {
QueueLock qlock = subjects.get(s);
if (qlock.requests.decrementAndGet() == 0) {
subjects.remove(s);
removed = true;
} else {
qlock.turn.release();
}
} finally {
subjectsLock.unlock();
}
return removed;
}
public List<String> getSubjects() {
List<String> subjectsBeingProcessed = new ArrayList<>();
subjectsLock.lock();
try {
// maintains insertion order, see https://stackoverflow.com/a/18929873/3080094
subjectsBeingProcessed.addAll(subjects.keySet());
} finally {
subjectsLock.unlock();
}
return subjectsBeingProcessed;
}
public static class SleepAction implements Runnable {
final int requestNumber;
final long sleepTime;
final String subject;
public SleepAction(int requestNumber, String subject, long sleepTime) {
this.requestNumber = requestNumber;
this.sleepTime = sleepTime;
this.subject = subject;
}
#Override
public void run() {
System.out.println(toString() + " sleeping for " + sleepTime);
sleep(sleepTime);
System.out.println(toString() + " done");
}
public String toString() {return timeSinceStart() + " " + subject + " [" + Thread.currentThread().getName() + "] " + String.format("%03d",requestNumber); }
}
public static final long START_TIME = System.currentTimeMillis();
public static String timeSinceStart() {
return String.format("%05d", (System.currentTimeMillis() - START_TIME));
}
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Here is my example but it does not execute. It's only working correctly for my first thread pool but the second thread pool was not run. Is it the correct way or not?
If it's correct, where did I make the mistake and if it's not, how do I implement multiple executor services?
In my example the save API executed successfully, and the book appointment method calls the book API successfully, but after the book API, the code does not execute and I'm wondering why.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyTestClass {
public static void main(String args[]) {
//Create class object
MyTestClass myObj = new MyTestClass();
// Create List A
List<String> a = new ArrayList<>();
a.add("Test1");
a.add("Test2");
a.add("Test3");
a.add("Test4");
//Create List B
List<String> b = new ArrayList<>();
b.add("Test1");
b.add("Test2");
b.add("Test3");
b.add("Test4");
b.add("Test5");
b.add("Test6");
b.add("Test7");
b.add("Test3");
b.add("Test4");
b.add("Test5");
b.add("Test6");
b.add("Test7");
//Call my method
myObj.myMethod(a, b);
}
//Multi-threading example in appointment book method execute first api but its not called the second api
void myMethod(List<String> listA, List<String> listB){
ExecutorService threadPool = Executors.newFixedThreadPool(listA.size());
List<Callable<Object>> tasks = new ArrayList<>();
for (String strA : listA) {
tasks.add(Executors.callable(new Thread() {
#Override
public void run() {
processA(strA);
}
}));
}
try {
//Execute first thread pool for save
threadPool.invokeAll(tasks);
} catch (InterruptedException e1) {
e1.printStackTrace();
System.out.println("Error while running threads");
}
threadPool.shutdown();
//Call book appointment api
bookAppointMent(listB);
}
//Book appointment
void bookAppointMent(List<String> listB) {
ExecutorService threadPool2 = Executors.newFixedThreadPool(listB.size());
List<Callable<Object>> tasks2 = new ArrayList<>();
for (String strB : listB) {
tasks2.add(Executors.callable(new Thread() {
#Override
public void run() {
// Add task
processB(strB);
}
}));
}
try {
//Execute thread pool2
threadPool2.invokeAll(tasks2);
} catch (InterruptedException e1) {
e1.printStackTrace();
System.out.println("Error while running threads");
}
//Shutdown pool-2
threadPool2.shutdown();
}
//Save appointment
public void processA(String a){
//Here its save API
System.out.println("Save A successfully...." + a);
}
//Book Appointment In this method only first api called but second one is not called
public void processB(String b){
//Here is First API call - This only called
System.out.println("Appointment booked successfully...." + b);
//Here is second API call - Its not called
processAfterAppBooked(b);
}
//Process after book app
public void processAfterAppBooked(String b) {
//Second api call - its not execute
System.out.println("After appointment booked " + b);
}
}
I have a User Interface(UI) class. It creates some thread (lets call it T) to do some work. I want my UI class to be notified when T is done working.
I think I need to create an event handler in UI class (among onClick() etc) and trigger it from T.
Question: Is this possible ? How ?
//to be clear, UI class does already have some event Handlers which are triggered by functions I didn't write. like onClick() , etc.
This is a fairly common requirement as you generally want to be doing as little as possible on the UI thread.
If you are using swing, have a look at the SwingWorker class. If you are not using swing, you might want to have a look at ExecutorService and FutureTask.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Futures {
public static void main(String[] args) {
UI ui = new UI();
FutureHandle<String> handle = new FutureHandle<String>(new BigJob());
FutureHandle<String> handle2 = new FutureHandle<String>(new BigJob());
ui.doUIStuff("Things can happen on the UI thread");
ui.startHeavyLiftingJob(handle);
ui.doUIStuff("I've got a big job running, but I'm still responsive");
ui.startHeavyLiftingJob(handle2);
}
/**
* Your UI class. Don't want to do anything big
* on the UI's thread.
*/
static class UI implements Listener<String> {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public void doUIStuff(String msg) {
System.out.println(msg);
}
public void startHeavyLiftingJob(FutureHandle<String> handle) {
System.out.println("Starting background task");
handle.setListener(this);
threadPool.execute(handle);
}
public void callback(String result) {
System.out.println("Ooh, result ready: " + result);
}
}
/**
* A handle on a future which makes a callback to a listener
* when the callable task is done.
*/
static class FutureHandle<V> extends FutureTask<V> {
private Listener<V> listener;
public FutureHandle(Callable<V> callable) {
super(callable);
}
#Override
protected void done() {
try {
listener.callback(get());
} catch (InterruptedException e) {
//handle execution getting interrupted
} catch (ExecutionException e) {
//handle error in execution
}
}
public void setListener(Listener<V> listener) {
this.listener = listener;
}
}
/**
* Class that represents something you don't want to do on the UI thread.
*/
static class BigJob implements Callable<String> {
public String call() throws Exception {
Thread.sleep(2000);
return "big job has finished";
}
}
interface Listener<V> {
public void callback(V result);
}
}
I am sorry that this is too long, and it may seem as too much asking, but If you can figure out what is wrong at a glance, please let me know.
In this program I try to input some words (phrase) from the keyboard every time taking one token and assign it to an object sharedStorer (then print the assigned value to keep track of what is input as I have a chain of words to input separately). This is done by one thread (Thread of class Retriever which implements Runnable)
There is another thread of class TokenReader that reads the value of sharedStorer and print it out. TokenReader waits for Retriever for input and when Retriever tries to input while TokenReader has not yet read the previous token Retriever waits.
The question I have is that at the end TokenReader waits forever for Retriever which has completed its task, and so the program never terminates.
Here is all 4 classes (and 1 Interface) I am using to perform the desired task.
package Multithreads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExerciseTest {
public static void main(String[] args) {
ExecutorService app=Executors.newFixedThreadPool(2);
Storer st=new SyncStorer();
System.out.println("Operation performed\t\t Value");
try{
app.execute(new Retriever(st));
app.execute(new TokenReader(st));
}catch(Exception e){
e.printStackTrace();
}
app.shutdown();
}
}
package Multithreads;
public interface Storer {
public void set(String token);
public String get();
}
package Multithreads;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Retriever implements Runnable {
private Scanner scanner;
private String token;
private String currentToken;
private Storer sharedStorer;
private Random rd=new Random();
public int tokenLength=0;
public Retriever(Storer st) {
sharedStorer=st;
}
public Retriever() {
}
#Override
public void run() {
System.out.println("Enter a phrase");
scanner = new Scanner(System.in);
token=scanner.nextLine();
StringTokenizer tokenizer=new StringTokenizer(token);
while(tokenizer.hasMoreTokens())
{
tokenLength++;
currentToken=tokenizer.nextToken();
try{
Thread.sleep(10*rd.nextInt(2000));
sharedStorer.set(currentToken);
}catch(NoSuchElementException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Done Inputting The phrase");
}
}
package Multithreads;
import java.util.Random;
public class TokenReader implements Runnable {
private Random rd=new Random();
private Storer sharedStorer;
Retriever rtr=new Retriever();
private int count=rtr.tokenLength;
public TokenReader(Storer st) {
sharedStorer=st;
}
#Override
public void run() {
String str="null";
int i=0;
try {
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer done reading");
}
}
package Multithreads;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncStorer implements Storer {
private Lock accessLock=new ReentrantLock();
private Condition canInput = accessLock.newCondition();
private Condition canRead = accessLock.newCondition();
private String string="null";
private boolean isEmpty=false;
#Override
public void set(String token) {
accessLock.lock();
try
{
while(isEmpty){
System.out.println("Retriever waiting");
canInput.await();
}
string=token;
isEmpty=true;
System.out.println("Retriever inputs\t\t "+string);
canRead.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
accessLock.unlock();
}
}
#Override
public String get() {
accessLock.lock();
try{
while(!isEmpty)
{
System.out.println("No token to read");
canRead.await();
}
isEmpty=false;
System.out.println("TokenReader reads\t\t "+string);
canInput.signal();
}catch(InterruptedException e)
{
e.printStackTrace();
}finally{
accessLock.unlock();
}
return string;
}
}
The problem that is causing the app to run forever is that this is an infinite loop:
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
because you are not decrementing i. And the interrupt-based mechanism you are trying to use to break out of the loop (via an exception!) is broken too.
The Thread.sleep(15*rd.nextInt(2000)) line looks like a hack so that you can get an InterruptedException when the task is interrupted, but:
the point of sleeping for a random number of milliseconds escapes me, and
it would be simpler to just call Thread.interrupted().
Besides, the approach isn't reliable anyway because there is a chance that the interrupt will happen after the point at which you are waiting / testing for it; i.e. in the get() call. And if that get() call is never going to return because the store is empty and the retriever has ended ... then you will wait "for ever".
There is one final problem. You need to call app.shutdownNow() if you want the executor service to interrupt the worker threads ...
If I was trying to implement this (using interrupts), I'd change it so that get and set didn't "gobble up" the interrupt. If they see the interrupt, they should either:
allow the InterruptedException to propagate (after relevant cleanup), or
set the thread's interrupted flag again in the exception handler.