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".
Related
I'm looking at other examples here and in other sites and I'm not understanding what I'm doing wrong. I'm trying to do a program that one thread sets the value of an object to the values 1 to 10, but I want to wait for it to change the value until other thread reads it, so I can print them and have a list from 1 to 10.
My readThread run method just loops from 1 to 10 calling the following method:
private synchronized int receive() {
try {
wait();
int value = this.mainThread.getValor();
notify();
return value;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
My writeThread run method just loops from 1 to 10 calling the following method:
private synchronized void send(int n) {
try {
this.mainThread.setValor(n);
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The main method is the following:
public static void main(String[] args) {
MainThread mt = new MainThread();
ReadThread rt = new ReadThread(mt);
WriteThread wt = new WriteThread(mt);
wt.start();
rt.start();
}
The class MainThead has the property "valor" defined with its getter and setter
Thank you for your help
There are a couple of obvious problems.
It looks as if you are synchronising on the same lock (there isn't enough code to be 100% sure). Generally you should create an object specifically to use as a lock.
send may be executed before receive. In that case the first notify will do nothing, and both threads will stall in wait.
In theory, there is no guarantee that wait will not wakeup spontaneously. For this and other reasons, you really want the wait inside a while loop.
I wrote below program in which even thread would print even numbers whereas odd thread would print odd numbers. In addition to the odd and even threads, I created a control thread, which decides if a number is odd or even and sets flag appropriately. Based on the flag which control thread sets, either odd or even thread will get chance to print.
I am using an array as source. The control thread increments the index so odd or even thread can retrieve the number from array and print.
The below is the complete code, with comments are well.
package com.example.practice;
public class OddEvenDemoVer2 {
// Since all of these variable are used in a synchronized block, I think we
// don't need them to be as volatile, as synchronized enforces
// memory-barrier and hence all thread would see latest values.
static boolean printEven = false;
static boolean printingDone = false;
static int index = 0;
static volatile boolean stop = false;
static volatile boolean oddThreadStarted = false;
static volatile boolean evenThreadStarted = false;
public static void main(String[] args) throws InterruptedException {
Object _controlLock = new Object();
Object _indexControlLock = new Object();
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
class ControlThread implements Runnable {
#Override
public void run() {
// Wait for proper initialization of odd and even threads.
while (!oddThreadStarted && !evenThreadStarted) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (; !stop;) {
// This is to make sure that we give chance to OddThread or
// EvenThread to print the values.
// Here, we are only setting the flag which thread should
// print the number, the advancing of index is done in
// another block.
synchronized (_controlLock) {
if (arr[index] % 2 == 0) {
printEven = true;
}
else {
printEven = false;
}
_controlLock.notifyAll();
}
// This is to make sure we advance index only when printing
// has been done either by OddThread or EvenThread
synchronized (_indexControlLock) {
while (printingDone != true) {
try {
_indexControlLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index++;
if (index > 9) {
stop = true;
}
}
}
}
}
class EvenPrintingThread implements Runnable {
#Override
public void run() {
evenThreadStarted = true;
// Loop until stop is signaled by ControlThread
for (; !stop;) {
synchronized (_controlLock) {
while (printEven != true) {
try {
_controlLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even printing thread --> " + arr[index]);
// This is to signal control thread that printing has
// been done and now index can be advanced.
synchronized (_indexControlLock) {
printingDone = true;
_indexControlLock.notify();
}
}
}
}
}
class OddPrintingThread implements Runnable {
#Override
public void run() {
oddThreadStarted = true;
// Loop until stop is signaled by ControlThread
for (; !stop;) {
synchronized (_controlLock) {
while (printEven != false) {
try {
_controlLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Odd printing thread --> " + arr[index]);
// This is to signal control thread that printing has
// been done and now index can be advanced.
synchronized (_indexControlLock) {
printingDone = true;
_indexControlLock.notify();
}
}
}
}
}
Thread controlThread = new Thread(new ControlThread());
controlThread.start();
Thread evenThread = new Thread(new EvenPrintingThread());
Thread oddThread = new Thread(new OddPrintingThread());
evenThread.start();
oddThread.start();
Thread.sleep(1000000L);
}
}
I expected this program will work , however it is behaving erratically. For example, one of the output is:
Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 1
...
Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 10
Odd printing thread --> 10
Odd printing thread --> 10
Odd printing thread --> 10
I saw online some other ways in which similar problem can be solved, however, when I started on this (without looking for ready made solution online), the above approach came to my mind. I don't want to abandon simply because it isn't working. I debugged, but didn't got a clarity as to what might be wrong in this approach.
What am I missing?
EDIT
Attaching the screen shot in which shows two threads "owning" same object id.
Depending on the expected behavior, it only needs one or two changes.
The output that you're seeing is not wrong. Your printingDone will never be set back to false, so the controller thread will happily keep incrementing your index once it gets the chance. The notifyAll() method will wake up suspended odd/even threads, but all threads using the same lock are still competing for synchronization. My guess is that the controller thread finishes the increment fast enough to compete and therefore you have a race condition with unreliable output.
If you want at least one line for each array element, just set printingDone back to false after you incremented the index in the controller thread:
index++;
if (index > 9) {
stop = true;
}
printingDone = false;
If you feel like you should only get one output per value, it also makes sense to suspend your odd/even threads whenever printingDone is set to true:
while (printingDone == true || printEven != true) { // or printEven == true for the odd printer
try {
_controlLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Edit: Oh, and the reason why you’re seeing even numbers printed by the odd thread is probably due to the fact that the odd thread acquires the controller lock after the index increment, but before the controller gets the chance to update printEven. Perhaps you should think of a way to both increment and update the boolean in the same code block.
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;
}
}
I was trying some concepts of multithreading learned recently but was not able to run it.
It gives IlleagalMonitorStateException but does not figure out the error why it is happening.
So about code-2 threads-reference names-filler & writter both are sharing an arraylist-filler is filling arraylist with integer(but will fill it upto 30) and after each number is added by filler and writter thread read the arraylist get the item writes it to file remove it from arraylist. For better understanding comment is added to code.
package com.utsav.pratice;
import java.io.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
//shared arraylist-synchronized
ArrayList<Integer> integerArrayList = new ArrayList<>();
//writter will write to this file numbers added to arraylist by filler and than will remove it from arraylist
FileOutputStream file = new FileOutputStream("Numbers.txt");
//filler will mark it true after completing all numbers
final boolean[] numbersCompleted = {false};
Thread filler=new Thread(new Runnable(){
#Override
public void run(){
//1-30 numbers one by one will be written to Arraylist
for (int i = 1; i < 31; i++) {
synchronized (integerArrayList) {
//if arraylist is not empty that means writter not performed on arraylist hence invoking wait to release lock so writter could perform
while(!integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is empty now lets fill it,notify that releasing lock and than put thread to sleep
integerArrayList.add(i);
System.out.println("Number added");
if(i==30){
numbersCompleted[0] =true;}
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Numbers adding completed");
}
});
Thread writter=new Thread(new Runnable(){
#Override
public void run(){
//if numbers are completed than nothing to write come out of loop
while(!numbersCompleted[0]) {
synchronized (integerArrayList) {
//if arraylist is empty than its time for filler to work hence putting thread to wait so lock could be released for filler
while (integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is not empty now lets write it & than remove it from arraylist,notify that releasing lock and than put thread to sleep
try (DataOutputStream fileWritter = new DataOutputStream(new BufferedOutputStream(file));) {
fileWritter.writeInt(integerArrayList.get(0));
System.out.println("Random number written");
} catch (IOException e) {
e.printStackTrace();
}
integerArrayList.remove(0);
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("File written completely");
}
});
//starting both threads-2cases filler takes the key-ok(will fill & wait) or filler takes the key(will wait since will be empty)
writter.start();
filler.start();
Here:
synchronized (integerArrayList)
You are synchronizing on your list.
But you are waiting/notify on this of your anonymous thread objects! And as the very first information in the javadoc says:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
So things should work when you change those to
integerArrayList.wait()
for example (all usage of wait/notify/...) !
And hint: don't do things like
final ArrayList<Integer> integerArrayList = new ArrayList<>();
just go for
List<Integer> numbers = new ArrayList<>();
Simply do not use the concrete impl class type as type of your variable; and also not as part of its name!
I have two threads running parallel, and to get information about their internal results, I have created int array of length 8. With respect to their id, they can update relative area on the statu array. They are not let to write others area. Moreover, to correctly get and display statu array, I try to write getStatu method. While getting the result, I want to block others to write to the statu array; unfortunately, I donot get how to block other to write the statu array while I am getting and displaying result in getStatu method. How?
Note: If there is a part to cause misunderstood, tell me my friend, I will fix
class A{
Semaphore semaphore;
int [] statu; // statu is of length 8
void update(int idOfThread, int []statu_){
try {
semaphore.acquire();
int idx = idOfThread * 4;
statu[idx] = statu_[0];
statu[idx+1] = statu_[1];
statu[idx+2] = statu_[2];
statu[idx+3] = statu_[3];
} catch (...) {
} finally {
semaphore.release();
}
}
int[] getStatu(){
// Block write access of threads
// display statu array
// return statu array as return value
// release block, so threads can write to the array
}
}
Apart from using another lock/snc mechanism than Semaphore, just a proposal to improve this a little.
Putting both status[4] arrays into a single array[8] is not hte best solution. Consider task A writing its quadruplet: it must lock out task B reading the same, but there's no point in locking out task B writing B's quadruplet, and vice versa.
Generally speaking, the granularity of what is being locked is one important factor: locking the entire database is nonsense (except for overall processing like backup), however locking individual fields of a record would produce excessive overhead.
There are possibly better ways to get to where you want to, but only you know what you are trying to do. Going with your own scheme, there are things you are doing wrong. First thing, currently you are not achieving the granular locking you are planning to. For that you must have an array of semaphores. So the acquisition will look something like
semaphore[idOfThread].acquire();
Secondly, one thing you've not realised is that controlled access to data among threads is a co-operative activity. You cannot lock on one thread and not care to deal with locking on another and somehow impose the access control.
So unless the caller of your getStatu() will use the same set of semaphores when inspecting the array, your best bet is for getStatu() to make a new int[] array, copying segments of each thread after locking with the respective semaphore. So the array returned by getStatu() will be a snapshot at the point of call.
Please try the below code it will work for you. call afterStatu() in it.
class A {
Semaphore semaphore;
int[] statu; // statu is of length 8
private boolean stuck;
public A() {
}
void update(int idOfThread, int[] statu_) {
// if true, control will not go further
while (stuck);
try {
semaphore.acquire();
int idx = idOfThread * 4;
statu[idx] = statu_[0];
statu[idx + 1] = statu_[1];
statu[idx + 2] = statu_[2];
statu[idx + 3] = statu_[3];
} catch (Exception e) {
} finally {
semaphore.release();
}
}
int[] getStatu() {
// Block write access of threads
stuck = true;
// display statu array
for (int eachStatu : statu) {
System.out.println(eachStatu);
}
// return statu array as return value
return statu;
}
public void afterStatu() {
getStatu();
// release block, so threads can write to the array
stuck = false;
}
}
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
int[] statu;
void update() {
lock.writeLock().lock();
try {
// update statu
} finally {
lock.writeLock().unlock();
}
}
int[] getStatu() {
lock.readLock().lock();
try {
// return statu
} finally {
lock.readLock().unlock();
}
}
Like ac3 said, only you know what you are trying to do.
Here's a solution that might be useful in the case where every thread that calls update() does so frequently, and calls to getStatu() are infrequent. It's complex, but it allows most of the update() calls to happen without any locking at all.
static final int NUMBER_OF_WORKER_THREADS = ...;
final AtomicReference<CountDownLatch> pauseRequested = new AtomicReference<CountDownLatch>(null);
final Object lock = new Object();
int[] statu = ...
//called in "worker" thread.
void update() {
if (pauseRequested.get() != null) {
pause();
}
... update my slots in statu[] array ...
}
private void pause() {
notifyMasterThatIAmPaused();
waitForMasterToLiftPauseRequest();
}
private void notifyMasterThatIAmPaused() {
pauseRequested.get().countDown();
}
private void waitForMasterToLiftPauseRequest() {
synchronized(lock) {
while (pauseRequested.get() != null) {
lock.wait();
}
}
}
//called in "master" thread
int[] getStatu( ) {
int[] result;
CountDownLatch cdl = requestWorkersToPause();
waitForWorkersToPause(cdl);
result = Arrays.copyOf(statu, statu.length);
liftPauseRequest();
return result;
}
private CountDownLatch requestWorkersToPause() {
cdl = new CountDownLatch(NUMBER_OF_WORKER_THREADS);
pauseRequested.set(cdl);
return cdl;
}
private void waitForWorkersToPause(CountDownLatch cdl) {
cdl.await();
}
private void liftPauseRequest() {
synchronized(lock) {
pauseRequested.set(null);
lock.notifyAll();
}
}