How to continuously scan input into console? - java

I have taken a task upon myself to learn Java. My idea was to create a simple game with only the text console. The "AI" (timer) will periodically send a string and the player has to write a correct string in response, otherwise s/he loses a life.
My first question therefore is: Is there a simple way to combine timer and scanner? I need it to constantly "watch" the console line for strings.
After some time of searching and tries where I mostly struggled to scan the text while generating or generate strings while scanning I found following code but it has an issue at:
if ((name =in.nextLine(2000)) ==null)
If I rewrite the condition to, for example, compare to !="a" instead of null, the code just ignores the condition and always writes "Too slow!" no matter what. If it is =="a" it always says Hello, a. I completely don't understand why, it seems to ignore the logic.
So the second question would have been, why does it ignore the logic when it is different? And how do I fix it?
public class TimedScanner
{
public TimedScanner(InputStream input)
{
in = new Scanner(input);
}
private Scanner in;
private ExecutorService ex = Executors.newSingleThreadExecutor(new ThreadFactory()
{
#Override
public Thread newThread(Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
public static void main(String[] args) {
TimedScanner in = new TimedScanner(System.in);
int playerHealth = 5;
System.out.print("Enter your name: ");
try {
while (playerHealth > 0) {
String name = null;
if ((name = in.nextLine(3000)) ==null) {
System.out.println(name);
System.out.println("Too slow!");
playerHealth--;
} else {
System.out.println(name);
System.out.println("Hello, " + name);
}
}
} catch (InterruptedException | ExecutionException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
public String nextLine(int timeout) throws InterruptedException, ExecutionException
{
Future<String> result = ex.submit(new Worker());
try
{
return result.get(timeout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
return null;
}
}
private class Worker implements Callable<String>
{
#Override
public String call() throws Exception
{
return in.nextLine();
}
}
}
This is very barebones idea of what it should do. In the while I plan to put in a randomly picked string, that will be compared with the console input and wrong input = playerHealth--; correct input something else.

2) why does it ignore the logic when it is different? And how do I fix it?
You've stated:
If I rewrite the condition to, for example, compare to !="a" instead
of null, the code just ignores the condition and always writes "Too
slow!" no matter what.
In Java, NEVER (or almost never) compare two strings using == or !=. A String is an Object so comparing them using == means comparing them by address and not by value. So
if ((name = in.nextLine(3000)) != "a")
will always (or almost always) return true because any string returned from in#nextLine, be it "a" or something different, will be allocated on the heap at a different address than your hardcoded "a" string. The reason I'm saying "almost" is because Java uses a concept of String Pool: when creating a new reference to a literal it checks whether a string is already present in the pool in order to reuse it. But you should never rely on ==. Instead, use Object.Equals().
More discusion about Java String Pool here.
1) Is there a simple way to combine timer and scanner?
Well, console UI it's not really friendly with multi-threading when it comes to reading user input, but it can be done...
Your code has an issue: whenever the player loses a life, it has to press Enter twice - when it loses 2 life consecutively, it has to press Enter 3 times in order to receive a positive feedback from "AI". This is because you're not killing the preceding thread / cancelling the preceding task. So I suggest the following code:
private static Scanner in;
public String nextLine(int timeout) throws InterruptedException, ExecutionException
{
//keep a reference to the current worker
Worker worker = new Worker();
Future<String> result = ex.submit(worker);
try
{
return result.get(timeout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
//ask the worker thread to stop
worker.interrupt();
return null;
}
}
private class Worker implements Callable<String>
{
//you want the most up-to-date value of the flag, so 'volatile', though it's not really necessary
private volatile boolean interrupt;
#Override
public String call() throws Exception
{
//check whether there's something in the buffer;
while (System.in.available() == 0){
Thread.sleep(20);
//check for the interrupt flag
if(interrupt){
throw new InterruptedException();
}
}
//once this method is called there's no friendly way back - that's why we checked for nr of available bytes previously
return in.nextLine();
}
public void interrupt(){
this.interrupt = true;
}
}

Related

Not reevaluating expensive data in different threads

i have such a method
public Object doSomethingExpensive(String x);
now if i processed this method i can save the result in a HashMap for example, they key is the String x and the value is the result Object.
If the data is present in this map, i dont have to process it again.
But now i get two requests in, at nearly the same time.
And in this case i want to let the second request wait, till the first one is done and the second requests can also get the result of the first one after it is calculated, so i dont have to calculate it twice or parallel twice.
the point is, i can't use
public synchronized Object doSomethingExpensive(String x);
because Object is something other if String x is something other.
So i need some synchronized on that String x.
But synchronized(x) isn't possible because string literals in java....
Also if there wouldn't be a String but an Object as x, then maybe i get in the second requests a similar Object with equal content related to request 1, but they are some other objects each.
Yeah so my question is, how to solve this, how can i prevent calculating for a String x its result twice in parallel, how can i synchronize it and caching the results in a HashMap for example.
I don't know if I understand your problem, If it's to avoid repeated calculation, this great book(Java Concurrency in Practice) gives a example of a solution:
private final Map<String, Future<Object>> cache
= new ConcurrentHashMap<String, Future<Object>>();
public Object doSomethingExpensive(String x) throws InterruptedException {
while (true) {
Future<Object> future = cache.get(x);
if (future == null) {
Callable<Object> callable = new Callable<Object>() {
#Override
public Object call() throws Exception {
// doSomethingExpensive todo
return new Object();
}
};
FutureTask<Object> futureTask = new FutureTask<>(callable);
future = cache.putIfAbsent(x, futureTask);
if (future == null) {
future = futureTask;
futureTask.run();
}
}
try {
return future.get();
} catch (CancellationException e) {
cache.remove(x);
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
}
}
}
EDIT:
From comments, using JAVA8#ConcurrentHashMap#computeIfAbsent, really really convenient :
ConcurrentHashMap<String, Object> concurrentHashMap = new ConcurrentHashMap<>();
public Object doSthEx(String key) {
return concurrentHashMap.computeIfAbsent(key, new Function<String, Object>() {
#Override
public Object apply(String s) {
// todo
return new Object();
}
});
}
Or use some library to get more comprehensive features as mentioned in comment:https://github.com/ben-manes/caffeine.

How to interrupt thread to do work and then sleep after doing work?

I want to have a thread which does some I/O work when it is interrupted by a main thread and then go back to sleep/wait until the interrupt is called back again.
So, I have come up with an implementation which seems to be not working. The code snippet is below.
Note - Here the flag is a public variable which can be accessed via the thread class which is in the main class
// in the main function this is how I am calling it
if(!flag) {
thread.interrupt()
}
//this is how my thread class is implemented
class IOworkthread extends Thread {
#Override
public void run() {
while(true) {
try {
flag = false;
Thread.sleep(1000);
} catch (InterruptedException e) {
flag = true;
try {
// doing my I/O work
} catch (Exception e1) {
// print the exception message
}
}
}
}
}
In the above snippet, the second try-catch block catches the InterruptedException. This means that both of the first and second try-catch block are catching the interrupt. But I had only called interrupt to happen during the first try-catch block.
Can you please help me with this?
EDIT
If you feel that there can be another solution for my objective, I will be happy to know about it :)
If it's important to respond fast to the flag you could try the following:
class IOworkthread extends Thread {//implements Runnable would be better here, but thats another story
#Override
public void run() {
while(true) {
try {
flag = false;
Thread.sleep(1000);
}
catch (InterruptedException e) {
flag = true;
}
//after the catch block the interrupted state of the thread should be reset and there should be no exceptions here
try {
// doing I/O work
}
catch (Exception e1) {
// print the exception message
// here of course other exceptions could appear but if there is no Thread.sleep() used here there should be no InterruptedException in this block
}
}
}
}
This should do different because in the catch block when the InterruptedException is caught, the interrupted flag of the thread is reset (at the end of the catch block).
It does sound like a producer/consumer construct. You seem to kind of have it the wrong way around, the IO should be driving the algorithm. Since you stay very abstract in what your code actually does, I'll need to stick to that.
So let's say your "distributed algorithm" works on data of type T; that means that it can be described as a Consumer<T> (the method name in this interface is accept(T value)). Since it can run concurrently, you want to create several instances of that; this is usually done using an ExecutorService. The Executors class provides a nice set of factory methods for creating one, let's use Executors.newFixedThreadPool(parallelism).
Your "IO" thread runs to create input for the algorithm, meaning it is a Supplier<T>. We can run it in an Executors.newSingleThreadExecutor().
We connect these two using a BlockingQueue<T>; this is a FIFO collection. The IO thread puts elements in, and the algorithm instances take out the next one that becomes available.
This makes the whole setup look something like this:
void run() {
int parallelism = 4; // or whatever
ExecutorService algorithmExecutor = Executors.newFixedThreadPool(parallelism);
ExecutorService ioExecutor = Executors.newSingleThreadExecutor();
// this queue will accept up to 4 elements
// this might need to be changed depending on performance of each
BlockingQueue<T> queue = new ArrayBlockingQueue<T>(parallelism);
ioExecutor.submit(new IoExecutor(queue));
// take element from queue
T nextElement = getNextElement(queue);
while (nextElement != null) {
algorithmExecutor.submit(() -> new AlgorithmInstance().accept(nextElement));
nextElement = getNextElement(queue);
if (nextElement == null) break;
}
// wait until algorithms have finished running and cleanup
algorithmExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.YEARS);
algorithmExecutor.shutdown();
ioExecutor.shutdown(); // the io thread should have terminated by now already
}
T getNextElement(BlockingQueue<T> queue) {
int timeOut = 1; // adjust depending on your IO
T result = null;
while (true) {
try {
result = queue.poll(timeOut, TimeUnits.SECONDS);
} catch (TimeoutException e) {} // retry indefinetely, we will get a value eventually
}
return result;
}
Now this doesn't actually answer your question because you wanted to know how the IO thread can be notified when it can continue reading data.
This is achieved by the limit to the BlockingQueue<> which will not accept elements after this has been reached, meaning the IO thread can just keep reading and try to put in elements.
abstract class IoExecutor<T> {
private final BlockingQueue<T> queue;
public IoExecutor(BlockingQueue<T> q) { queue = q; }
public void run() {
while (hasMoreData()) {
T data = readData();
// this will block if the queue is full, so IO will pause
queue.put(data);
}
// put null into queue
queue.put(null);
}
protected boolean hasMoreData();
protected abstract T readData();
}
As a result during runtime you should at all time have 4 threads of the algorithm running, as well as (up to) 4 items in the queue waiting for one of the algorithm threads to finish and pick them up.

Seat booking using synchronized block

I am trying to implement seat booking validation using a synchronized block like this:
synchronized(this) {
int seatsBooked = GrantAssessment.countByExamSessionAndExamDateBetweenAndIsCancelled(examSession,now,now+1,false)
int seatsRemaining = examSession.maxSeat - seatsBooked
if(seatsRemaining<1){
throw new CustomValidationException("All seats booked...")
}
// assign assessment which increases countByExam... query count by 1
grantAssessment = assignAssessment(examCommerce,examSession,examDate,identificationType,idNumber)
}
assignAssessment() method code is as follows:
def assignAssessment(ExamCommerce examCommerce, ExamSession examSession,Date examDate,IdentificationType identificationType,String idNumber) {
.................
examSession.addToGrantAssessmentList(grantAssessment)
..............................
grantAssessment.save(failOnError: true,flush: true)
examSession.save(failOnError: true,flush: true)
return grantAssessment
}
When I hit using browser 1(different thread) it enters the synchornized block and assigns a seat. When browser 2(thread 2, almost same time) enters the block the query count returned by the code below :
GrantAssessment.countByExamSessionAndExamDateBetweenAndIsCancelled(examSession,now,now+1,false)
is same.But the same thread shows reduced value(correct) after synchronized block.
Due to this, both the threads assigns the seat even if totalSeat is equal to 1.
How to handle to concurrency such that availableSeats value should be calculated correctly in a synchronized way. Is JMS OK for such scenarios ?
Seems like you are using different monitors.
For example the following can lead to the same state as you described both the threads assigns the seat even if totalSeat is equal to 1.
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
boolean bookTwoSeatsInParallel() {
Future<Integer> res1 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(this) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
Future<Integer> res2 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(this) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
}
res1.get().equals(res2.get()) could be true. This example is a bit redundant but it shows the case when different threads use different monitors in a try to achieve valid synchronized state.
To fix this you should synchronize on the same monitor, like this
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
private final Object bookingMonitor = new Object();
boolean bookTwoSeatsInParallel() {
Future<Integer> res1 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(bookingMonitor) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
Future<Integer> res2 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(bookingMonitor) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
}
Note that all variables you read/modify inside the synchronized(this) {...} block shouldn't be read/modified from somewhere else without synchronization on the same monitor. In other case it can lead to Thread Interference and Memory Consistency Errors
Is JMS OK for such scenarios ?
Definitely you can use JMS, pass booking requests through it to the only worker thread. But you don't need such a complex solution for this simple case.

Binary Semaphores and Buffers to sequentially print

I'm attempting to print a combination of characters.
Character 1 and 2 must be in sequence as follows: 1212121212. Character 3 prints intermittently, but must not exceed Character 2.
I have managed the first part of the task (1 and 2), but struggling with the introduction of 3. I know I need to use a counting semaphore to crack it.
This is for school, so please could you avoid pasting any code and just give me some pointers? I'm just showing two classes: my buffer, and Threads that print the characters.
Thanks.
public class PrintLetterA extends Thread {
private char letter;
private Buffer buffer;
public PrintLetterA(char letter, Buffer b) {
this.letter = letter;
buffer = b;
}
public void run() {
while (true) {
if (letter == 'F') {
Object a = new Object();
buffer.put(a);
System.out.println("" + letter);
try {
Thread.sleep( (int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (letter == 'G'){
Object a = buffer.get();
System.out.println("" + letter);
try {
Thread.sleep( (int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
public class Buffer {
private Object message = null;
BinarySemaphore Fbinary = new BinarySemaphore(1);
BinarySemaphore Gbinary = new BinarySemaphore(0);
public synchronized void put(Object message) {
try {
Fbinary.P();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.message = message;
Gbinary.V();
}
public synchronized Object get() {
try {
Gbinary.P();
} catch (InterruptedException e) {
e.printStackTrace();
}
Object m = message;
Fbinary.V();
return m;
}
First of all, consider creating two different classes for your threads (and possibly a common abstract superclass) instead of the if/else fork inside the run().
Now, take a look at the Semaphore class, be sure to read the description in the beginning of that page, it is really helpful to understand the concept. Basically, there are two methods you care about: acquire and release. Each time you print your "2", you will call the release method. This increases the number of "permits" that the semaphore holds. Now, in the other thread, just before printing "3", you will call acquire, it will check if there are any permits available, and if not , it'll block and wait, otherwise, it will decrease the number, and return, so that you can print your "3".
When you use it this way, the number of permits held by the semaphore at any given moment will reflect how many more "2"s have been printed than "3"s so far. There will never be more 3s than 2s, because acquire will not allow the number of permits go negative, if it happens to be 0, it will force your thread to wait until the other one prints another "2" and calls "release".

Will the assignment of value in a Java Boolean object cause re-allocation in memory

I have the following piece of code
Boolean flag = new Boolean(false);
flag = true;
Will the second line (assignment) cause a recreation of the initial object (basically a call to new()) in the JVM? I am asking because I am using a Boolean object to synchronize multiple threads, and I am afraid that if a re-initialization takes places, the waiting threads will not see the change in value.
In my application, there are multiple threads that are given a reference to the previous Boolean object. Only one thread changes the objects value to true, and the rest wait until the object's value becomes true. So, if T1 is the thread that changes the value, its code is like:
synchronized(flag) {
flag = true;
flag.notifyAll();
}
and the rest of the threads (T2) will have code like:
synchronized(flag) {
while(flag == false)
wait();
if(flag == true) {
//do something
}
}
Therefore, the question is that after the assignment of true to flag, will the other threads (T2) still have access to the original object?
Thanks,
Nick
The assignment flag = false is a boxing conversion. It will get compiled as flag=Boolean.valueOf(false) which will end up returning the constant Boolean.FALSE.
So the answer is, it will not create a new object but it will change the variable flag as it assigns an instance distinct from your previous result of new Boolean(false).
It’s not quite clear what you are actually doing but in general, synchronizing on a mutable variable is broken design.
The problem is that you are mixing the value that makes up your condition and the object to synchronize on. The simplest implementation of your updated intention is to use a simple boolean flag and synchronize on the instance that contains the flag:
class WithFlag {
private boolean flag;
public synchronized void setToTrue() {
if(!flag) {
flag=true;
notifyAll();
}
}
public synchronized void waitForTrue() throws InterruptedException {
while(!flag) wait();
}
}
Note that declaring an instance method synchronized is similar to wrap its code with synchronized(this) { … }
If you want to use a boolean to synchronize threads, you should consider using AtomicBoolean, which is specifically designed for this purpose.
The other answers have already explained that when you say flag=false, it is a boxing conversion which will return the constant Boolean.FALSE. One important point that the other answers have covered but not emphasized on is that when you obtain a lock on two Boolean objects that were assigned the same value through a boxing conversion, it is as good as obtaining a lock on one Boolean object.
My answer attempts to give an example to explain this. Consider the following code that creates two threads that obtain a lock on a Boolean.
public class BooleanTest {
public static void main(String[] args) {
BooleanTest test = new BooleanTest();
test.booleanTest();
}
private void booleanTest() {
BooleanLockTester booleanLock1 = new BooleanLockTester();
booleanLock1.setBooleanLock(true);
BooleanLockTester booleanLock2 = new BooleanLockTester();
booleanLock2.setBooleanLock(true);
BooleanLocker booleanLocker1 = new BooleanLocker(booleanLock1);
BooleanLocker booleanLocker2 = new BooleanLocker(booleanLock2);
Thread threadOne = new Thread(booleanLocker1);
Thread threadTwo = new Thread(booleanLocker2);
threadOne.start();
threadTwo.start();
}
private class BooleanLocker implements Runnable {
private BooleanLockTester booleanLockObj;
public BooleanLocker(BooleanLockTester booleanLockObj) {
this.booleanLockObj = booleanLockObj;
}
#Override
public void run() {
booleanLockObj.testLockOnBoolean();
}
}
private class BooleanLockTester {
private Boolean booleanLock = false;
public synchronized void testLockOnBoolean() {
synchronized (booleanLock) {
for (int i = 0; i<1000000000; ++i) {
System.out.println(Thread.currentThread().getName());
}
}
}
public void setBooleanLock(Boolean booleanLock) {
this.booleanLock = booleanLock;
}
}
}
In the above example, the two threads will never be able to enter the for loop together. When you run the program, you will see that the thread that starts first will start printing on the console and only when it is finished, the next thread will start printing to the console.
Let's make a small change in the above code :
Change the following line in the code :
booleanLock2.setBooleanLock(true);
To this :
booleanLock2.setBooleanLock(false);
You will now see that the threads stop behaving and print to the console in a random order. This is because the threads now obtain a lock on two different objects.

Categories

Resources