Return from await() from other method - java

I’m newbie in Play! and I have one question about asynchronous programming in HTTP.
I have a piece of code like this:
public void someMethod() {
for (int i = 0; i < 100; i++) {
doSomething();
await(someTime);
}
}
This method is invoked by user by sending GET/POST request.
It does some computations (doSomething()) and after that it waits some time.
But: the user has to have ability to “return” from await(someTime) and the loop should continue next iteration without waiting all the “someTime” time.
The example code:
public void nextAwait() {
continueАForLoop();
}
The user invokes nextAwait() method by GET/POST.
If it is invoked, the loop will continue and doSomething() will be (has to be) invoked immediately!
So, is it possible in Play?
Thanks in advance for answers :)

The simple answer to this, is to wait for a shorter period of time, then check some value for user interaction, and then continue waiting.
for example, let's assume your total wait time is 10 seconds
public void someMethod() {
for (int i = 0; i < 100; i++) {
doSomething();
for (int j=0; j<10; j++) {
if (!userInterrupt) await("1s");
}
}
}
So, this breaks your wait down to 1 second chunks, and checks a value to see if the user has interrupted the wait. It means that the user will wait a maximum of 1 second before the processing is released.

I don't know if it works this way but you could try something like that: (You have a field monitor = new Object() somewhere)
synchronized ( this.monitor ) {
this.monitor.wait( someTime );
}
and in the other method you call:
synchronized ( monitor ) {
this.monitor.notifyAll();
}

Related

How to use multithreads in java so that they take turns in a game

Trying to use n number of threads, where there are two different types of thread that needs to be being swapped between. So goes t1, x1, t2, x2, t3, x3.... where x and t are thread classes. I've been trying to use wait and notify but cant seem to get this to work. Or synchronisation.
All threads all need to access and modify the same list-array in their respective "turns" which i thought could be its own synchronised class, yet maybe an atomic variable would work also?
Any help is very appreciated.
"""
public String startGame(int threadNumbers, List<String> result, String fileLoc) throws IOException {
Players[] playerThreads = new Players[threadNumbers];
Card[] cardThreads = new Card[threadNumbers];
cardDeck cardD = new cardDeck(fileLoc);
for (int i = 0; i < (threadNumbers); i++) {
System.out.println(i);
playerThreads[i] = new Players(i+1, cardD);
if (i>0) {
playerThreads[i-1].next = cardThreads[i-0];
}
if (i==threadNumbers-1) {
playerThreads[i].next = cardThreads[0];
}
cardThreads[i] = new Card(i+1);
if (i>0) {
cardThreads[i-1].next = playerThreads[i-0];
}
if (i==threadNumbers-1) {
cardThreads[i].next = playerThreads[0];
}
new Thread(playerThreads[i]).start();
new Thread(cardThreads[i]).start();
Thread.yield();
Thread.yield();
}
synchronized (playerThreads[0]) {
playerThreads[0].notify();
"""
This is not working, but what needs to happen is they take a card from the deck in a looping way then start the game after they have a hand. The card threads also are just hands but are different as they dont "play" but just work.
Since this seems to be all in one (JVM) process, there's no need for multiple threading here: Just use a queue to track whose turn it is and who's turn it is next. After a player's turn, add them back to the end of the queue.
And actually, now that I think about it there's no reason this same solution couldn't work with multiple processes or over sockets.
Just use a queue
-- Edit --
So what you need is a class with a blocking method. For example
public class Player implements Runnable {
private Move nextMove;
public Move synchronized getMove() {
if (!nextMove) {
this.wait([add timeout if appropriate]);
}
Move next = nextMove;
nextMove = null;
return next;
}
public void run() {
while (true) {
Thread.sleep([someRandomTime]);
synchronized(this) {
if (nextMove == null) {
nextMove = new Move();
this.notify();
}
}
}
}
}
So still using your queue, you go through each Player and call getMove(), which will block until the player posts a move.
BTW, this kind of blocking is similar to how InputStream.read(buffer) works in sockets. The thread calling read waits until the other side of the stream sends some content.
-- Edit 2 --
And just as a reminder: Don't use synchronized, wait, notify or notifyAll on a Thread object.

Issues with Threads. Trying to test a timer that utilizes threads and seem to get stuck in a loop

My TEST creates an instance of SimpleTimer with 1000 as a milliseconds measure to delay the thread by 1 second.
#Test
public void testSimpleTimerAsThread() throws InterruptedException
{
SimpleTimer st = new SimpleTimer(1000);
st.start();
Thread.sleep(250);
for(int x = 0; x<5; x++)
{
assertEquals(x, st.getRound());
Thread.sleep(1000);
}
}
My METHOD
timeChanged() just updates the round number and calls for all observers to update their time.
public void start()
{
for(int r = 0; r<5; r++)
{
try
{
timeChanged();
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
SimpleTimer extends Thread and implements an interface that doesn't really mess with this code.
When I run this i get the java assertion error saying it expected 0 but was 5 so x never incremented and the round increased by 5.
Your SimpleTimer works in the same thread as the rest, so when you call st.start() what happens is it goes straight there and executes everything, then the rest of your test is executed. You need to put all of your SimpleTimer logic in run method instead of start method and remove start method completely, Thread class already has it implemented in the right way (but keep call to st.start(), it's ok, that's how you start a new Thread). But even then it's not gonna work as expected, but this will actually be concurrency problem, not a mistake. I mean there is a slight possibility that it's gonna work (only sometimes, not always), because of the delays, but relying on delays it's not really a good idea.

while loop in seperate thread continues running after condition has been changed via seperate method in main thread

public void taskInProgress(String jobMessage) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
runningTask = true;
Test:
while (runningTask) {
for (int i = 0; i < runningStars.length; i++) {
System.out.print(runningStars[i].concat(" ").concat(jobMessage));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
t.start();
}
public void taskFinnished(String msg) {
this.runningTask = false;
System.out.println("\r".concat(ok(msg)));
}
The wished effect is, that stars get printed as an infinite progress bar in the console, that is the for loop nested in the while loop, and when i call a method, the stars get replaced with a status and message, and they get stopped. I implemented this with latching the class field runningTask in taskFinnished().
My problem is, even after breaking the while loop, stars still get printed to the console. The loop continues execution even after the while loop condition returns false, for a good few seconds.
Screenshot:
As seen here, it still says Extracting tar archive, after the taskFinnished() method has been called and the while loop broken.
Here is the code that uses these implementations:
tc.taskInProgress("Extracting tar archive");
// do long operation on main thread, keep console animation running in seperate thread, and return exit int, Unix style
if (exit == 0) {
tc.taskFinnished("Tar finished without errors");
// This breaks the while loop, but more stuff gets printed even after breaking loop
} else {
// failed, handle it
}
Try to replace
for (int i = 0; i < runningStars.length; i++)
with
for (int i = 0; i < runningStars.length && runningTask; i++)
Your boolean flag (runningTask) must be declared volatile. Otherwise, there is no guarantee that the running thread sees the change made by the main thread.
An alternative would be to use an AtomicBoolean instead. But even better, you should use the mechanism that already exists to ask threads to stop running: interrupting the thread (by calling interrupt() on it). The running thread would have to regularly check if the current thread has been interrupted, using Thread.currentThread().isInterrupted().
The advantage of this mechanism over a custom boolean flag is that it the running thread is blocked waiting or sleeping, it will immediately go out of its waiting/sleeping state, by throwing an InterruptedException.
You should catch that exception, but instead of just ignoring it as you're doing, you should instead stop running ASAP.

Wait x seconds or until a condition becomes true

How to wait x seconds or until a condition becomes true? The condition should be tested periodically while waiting. Currently I'm using this code, but there should be a short function.
for (int i = 10; i > 0 && !condition(); i--) {
Thread.sleep(1000);
}
Assuming you want what you asked for, as opposed to suggestions for redesigning your code, you should look at Awaitility.
For example, if you want to see if a file will be created within the next 10 seconds, you do something like:
await().atMost(10, SECONDS).until(() -> myFile.exists());
It's mainly aimed at testing, but does the specific requested trick of waiting for an arbitrary condition, specified by the caller, without explicit synchronization or sleep calls. If you don't want to use the library, just read the code to see the way it does things.
Which, in this case, comes down to a similar polling loop to the question, but with a Java 8 lambda passed in as an argument, instead of an inline condition.
I didn't find a solution in the JDK. I think this feature should be added to the JDK.
Here what I've implemented with a Functional Interface:
import java.util.concurrent.TimeoutException;
import java.util.function.BooleanSupplier;
public interface WaitUntilUtils {
static void waitUntil(BooleanSupplier condition, long timeoutms) throws TimeoutException{
long start = System.currentTimeMillis();
while (!condition.getAsBoolean()){
if (System.currentTimeMillis() - start > timeoutms ){
throw new TimeoutException(String.format("Condition not met within %s ms",timeoutms));
}
}
}
}
Have you thought about some classes from java.util.concurrent - for example a BlockingQueue?
You could use:
BlockingQueue<Boolean> conditionMet = new BlockingQueue<Boolean>;
conditionMet.poll(10,TimeUnit.SECONDS);
And then in the code that changes your condition do this:
conditionMet.put(true);
EDIT:
Another example form java.util.concurrent may be CountDownLatch:
CountDownLatch siteWasRenderedLatch = new CountDownLatch(1);
boolean siteWasRendered = siteWasRenderedLatch.await(10,TimeUnit.SECONDS);
This way you'll wait 10 seconds or until the latch reaches zero. To reach zero all you have to do is:
siteWasRenderedLatch.countDown();
This way you won't need to use locks which would be needed in Condition examples presented by #Adrian. I think it's just simpler and straight-forward.
And if you don't like the naming 'Latch' or 'Queue' you can always wrap it into your own class called i.e. LimitedTimeCondition:
public class LimitedTimeCondition
{
private CountDownLatch conditionMetLatch;
private Integer unitsCount;
private TimeUnit unit;
public LimitedTimeCondition(final Integer unitsCount, final TimeUnit unit)
{
conditionMetLatch = new CountDownLatch(1);
this.unitsCount = unitsCount;
this.unit = unit;
}
public boolean waitForConditionToBeMet()
{
try
{
return conditionMetLatch.await(unitsCount, unit);
}
catch (final InterruptedException e)
{
System.out.println("Someone has disturbed the condition awaiter.");
return false;
}
}
public void conditionWasMet()
{
conditionMetLatch.countDown();
}
}
And the usage would be:
LimitedTimeCondition siteRenderedCondition = new LimitedTimeCondition(10, TimeUnit.SECONDS);
//
...
//
if (siteRenderedCondition.waitForConditionToBeMet())
{
doStuff();
}
else
{
System.out.println("Site was not rendered properly");
}
//
...
// in condition checker/achiever:
if (siteWasRendered)
{
condition.conditionWasMet();
}
Have a look at Condition.
Conditions (also known as condition queues or condition variables)
provide a means for one thread to suspend execution (to "wait") until
notified by another thread that some state condition may now be true.
Because access to this shared state information occurs in different
threads, it must be protected, so a lock of some form is associated
with the condition. The key property that waiting for a condition
provides is that it atomically releases the associated lock and
suspends the current thread, just like Object.wait.
A Condition instance is intrinsically bound to a lock. To obtain a
Condition instance for a particular Lock instance use its
newCondition() method.
EDIT:
Related question Sleep and check until condition is true
Related question is there a 'block until condition becomes true' function in java?
You may want to use something like the code below (where secondsToWait holds the maximum number of seconds you want to wait to see if the condition() turns true. The varialbe isCondetionMet will contain true if the condition was found, or false if the code timed out waiting for the condition.
long endWaitTime = System.currentTimeMillis() + secondsToWait*1000;
boolean isConditionMet = false;
while (System.currentTimeMillis() < endWaitTime && !isConditionMet) {
isConditionMet = condition();
if (isConditionMet) {
break;
} else {
Thread.sleep(1000);
}
}
I'm using the following adaptation of the original question's solution:
public class Satisfied {
public static boolean inTime(Callable<Boolean> condition, int timeoutInSecs) {
int count;
try {
for (count = 1; count < timeoutInSecs * 20 && !condition.call(); count++)
Thread.sleep(50);
return (count < timeoutInSecs * 20);
} catch (Exception e) {
throw new AssertionError(e.getMessage());
}
}
}
When used in testing, it appears like this:
assertThat(Satisfied.inTime(() -> myCondition(), 5)).isTrue();
Using await Awaitility:
Awaitility.with().pollDelay(1000, TimeUnit.MILLISECONDS).await().until(() -> true);

How to make threads in Java run concurrently

I'm trying out this code and I'm a bit confused/surprised at the output I'm getting. I'm still new to Java but I'm aware that threads should normally run concurrently. It seems my "printB" thread here waits for the "printA" thread before it starts executing. I've run the program several times (hoping to get a mixture of both threads' outcome i.e. something like: a, a, b, a, b, a...) but still I get the same output (i.e. "A" getting printed first, before "B"). Why is this happening and how can I alter the code to start behaving normally?
Any inputs/suggestions would be much appreciated. Thanks.
Also, I'm trying out the same code using the extends Thread method and it doesn't work.
class PrintChars implements Runnable{
private char charToPrint;
private int times;
public PrintChars(char c, int t){
charToPrint = c;
times = t;
}
public void run(){
for (int i=0; i<times; i++)
System.out.println(charToPrint);
}
public static void main(String[] args){
PrintChars charA = new PrintChars('a', 7);
PrintChars charB = new PrintChars('b', 5);
Thread printA = new Thread(charA);
Thread printB = new Thread(charB);
printA.start();
printB.start();
}
}
Extends Thread method below:
class PrintChars extends Thread {
private Char charToPrint;
private int times;
public PrintChars(char c, int t){
charToPrint = c;
times = t;
}
public void run (){
for(int i =0; i<times; i++)
System.out.println(charToPrint);
}
PrintChars printA = new PrintChars('a', 7);
PrintChars printB = new PrintChars('a', 5);
printA.start();
printB.start();
}
In multithreading, usually you can't make any assumption about the output.
Perhaps the time used to create the thread is very long, hence the previous thread has time to complete entirely, since its execution is very short.
Try with 7000 and 5000 instead of 7 and 5.
Each thread takes time to start and can run to completion very quickly. I suggest you add Thread.sleep(500); after each line printed.
try {
for(int i =0; i<times; i++) {
System.out.println(charToPrint);
Thread.sleep(500);
}
} catch(InterruptedException ie) {
}
Try running it a few more times. When I tried it with 700/500 I noticed some interweaving.
Thread scheduling is not deterministic. It's perfectly fine for the OS to schedule one thread, and only schedule the second after the first has completed.
If you think about it from the OS' point of view, it makes sense.. If somebody asked you to do two tasks, it may be more efficient to do one and then the other.
When the task takes too long to execute, as an OS you'll probably want to task switch and do something on the other task as otherwise the other task won't progress at all, and the app. that issued the task will feel discriminated.
You can see this by making your task run longer, e.g. by adding Thread.sleep statements or calculating PI or something (or just loop for more than 7, like 70000).
I think the execution times for your threads are too short to notice an effect. You can try higher values for times. I would try something >10000. Another option is to increase the execution time by making the method slower:
public void run(){
for (int i = 0; i < times; i++) {
System.out.println(charToPrint);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Your code is behaving normally only, if your expectation is to have mixture of a and b's printed, then you should sufficiently print chars not just couple of times, or use Thread.sleep() or do a busy wait running a for loop doing nothing for a million times.

Categories

Resources