Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I was trying to write a code where multiple threads call methods on a shared object to increment/decrement/print a counter stored in it. What I also want are these numbers to vascillate between 0 and 8. That is the output might look like something below:
0123234567654566677877666655....
Can somebody look at what I have cranked out and give me some pointers on whether I am on the right track:
My shared object:
public class SyncObj{
private int i;
public synchronized void inc(){
if(i<8)
i++;
}
public synchronized void dec(){
if(i > 0)
i--;
}
public synchronized void print(){
System.out.print(i);
}
}
To prevent starvation on the print and to make sure every inc/dec gets printed, I can have a private variable called hasPrinted and rewrite the class as follows:
public class SyncObj{
private int i;
//Changed Boolean to boolean as Keith Randall pointed out
private boolean hasPrinted = false;
public synchronized void inc(){
if(i<8 && hasPrinted){
i++;
hasPrinted = false;
}
}
public synchronized void dec(){
if(i > 0 && hasPrinted){
i--;
hasPrinted = false;
}
}
public synchronized void print(){
System.out.print(i);
hasPrinted = true;
}
}
Can somebody go over the above snippet and review it for pitfalls and gotchas?
Thanks
You should get used to using a queue for printing.
public class SyncObj {
private volatile int i;
private BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>();
public synchronized void inc() {
if (i < 8) {
i++;
q.add(i);
}
}
public synchronized void dec() {
if (i > 0) {
i--;
q.add(i);
}
}
public void print() {
for (Integer i = q.poll(); i != null; i = q.poll()) {
System.out.print(i);
}
}
private static volatile boolean stop = false;
public static void main(String[] args) throws InterruptedException {
final SyncObj o = new SyncObj();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.inc();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.dec();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.print();
}
}
}).start();
Thread.currentThread().sleep(1000);
stop = true;
}
}
My output looks like this:
1012345678765432101234567876543210123456787654321012345678765432101234567876543210123456787654321012345678
Boolean -> boolean, no point in having an object instead of a primitive type.
Your first code is fine. Your second code doesn't solve your requirements of preventing starvation or making sure every inc/dec gets printed. Why not just have inc/dec print the value itself?
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
Improve this question
i have this code and i cant understand why main thread doesn't print false after 1sec ???
public abstract class Callable<E> implements Runnable {
private E val=null;
protected abstract E call();
public synchronized boolean isReady()
{
if(val!=null)
return true;
return false;
}
public synchronized E waitForValue() throws InterruptedException
{
while(!isReady())
{
wait();
}
return val;
}
public synchronized void run()
{
E temp = call();
val = temp;
notifyAll();
}
public static void main(String[] args) throws InterruptedException
{
Callable<String> c = new Callable<String>() {
protected String call() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return "AAA";
}};
new Thread(c).start();
Thread.sleep(1000);
System.out.println(c.isReady());
System.out.println(c.waitForValue());
System.out.println(c.isReady());
}
}
if i change synchronized of method run like that it works
#Override
public void run() {
E temp = call();
synchronized (this) {
val = temp;
isReady = true;
notifyAll();
}
}
if thread sleep it doesn't release the lock of the object ?
and about wait it release the lock right ?
in the last i should print
false //after 1sec
AAA //after 4sec
true
The documentation can answer questions like this, and usually does.
Thread.sleep() does not release the monitor (or 'lock').
Object.wait() does release the monitor.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
public class Chat {
int flag=0;
public synchronized void Friend1(String msg) {
if(flag>0) {
try {
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag=1;
notify();
}
public synchronized void Friend2(String msg) {
if(flag==0) {
try {
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag=0;
notify();
}
public synchronized void Friend3(String msg) {
if(flag<0) {
try {
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag=(-1);
notify();
}
}
public class T1 implements Runnable {
Chat m;
String[] s1= {"Hi","How are you all?","Why what happened","Yes, We are in a hectic situation but we have to continue our studies and be strong inside","Fave faith in Allah! Eveything will be ok"};
public T1(Chat m1) {
this.m=m1;
new Thread(this, "Friend1").start();
}
public void run() {
for(int i=0; i<s1.length; i++) {
m.Friend1(s1[i]);
}
}
}
public class T2 implements Runnable{
Chat m;
String[] s2= {"Hy","I am fine","Is there anything wrong?","There is nothing we can do about in this pandemic situation but to study and pray","Everything will be fine soon"};
public T2(Chat m2) {
this.m=m2;
new Thread(this, "Answer").start();
}
public void run() {
for(int i=0; i<s2.length; i++) {
m.Friend2(s2[i]);
}
}
}
public class T3 implements Runnable {
Chat m;
String[] s3= {"Hello","I am not fine","I am very depressed about my online classes","I feel too much preassure","Yeap I will start praying to Allah that everything comes around"};
public T3(Chat m3) {
this.m=m3;
new Thread(this, "Friends3").start();
}
public void run() {
for(int i=0; i<s3.length; i++) {
m.Friend3(s3[i]);
}
}
}
public class Main {
public static void main(String[] args) {
Chat m=new Chat();
new T1(m);
new T2(m);
new T3(m);
}
}
Output is:
Hi
Hy
How are you all?
I am fine
Why what happened
Is there anything wrong?
Yes, We are in a hectic situation but we have to continue our studies and be strong inside
There is nothing we can do about in this pandemic situation but to study and pray
Fave faith in Allah! Eveything will be ok
Everything will be fine soon
Hello
In your case you know that every thread should print phrase after previous:
2 after 1
3 after 2
1 after 3
So you can create variable that will be store number of the thread that shouldmake action now:
AtomicInteger currentSpeaker = new AtomicInteger(1);
Every thread can check this var before printing next phrase and set new value for next thread:
public class T1 implements Runnable {
Chat m;
String[] s1 = {"Hi", "How are you all?", "Why what happened", "Yes, We are in a hectic situation but we have to continue our studies and be strong inside", "Fave faith in Allah! Eveything will be ok"};
public T1(Chat m1) {
this.m = m1;
new Thread(this, "Friend1").start();
}
public void run() {
for (int i = 0; i < s1.length; i++) {
while (currentSpeaker.get() != 1) delay(100L);
m.Friend1(s1[i]);
currentSpeaker.set(2);
}
}
}
public class T2 implements Runnable {
Chat m;
String[] s2 = {"Hy", "I am fine", "Is there anything wrong?", "There is nothing we can do about in this pandemic situation but to study and pray", "Everything will be fine soon"};
public T2(Chat m2) {
this.m = m2;
new Thread(this, "Answer").start();
}
public void run() {
for (int i = 0; i < s2.length; i++) {
while (currentSpeaker.get() != 2) delay(100L);
m.Friend2(s2[i]);
currentSpeaker.set(3);
}
}
}
public class T3 implements Runnable {
Chat m;
String[] s3 = {"Hello", "I am not fine", "I am very depressed about my online classes", "I feel too much preassure", "Yeap I will start praying to Allah that everything comes around"};
public T3(Chat m3) {
this.m = m3;
new Thread(this, "Friends3").start();
}
public void run() {
for (int i = 0; i < s3.length; i++) {
while (currentSpeaker.get() != 3) delay(100L);
m.Friend3(s3[i]);
currentSpeaker.set(1);
}
}
}
I created method delay to make code little clear for reading:
public static void delay(long t) {
try {
Thread.sleep(t);
} catch (InterruptedException e) {}
}
Output:
Hi
Hy
Hello
How are you all?
I am fine
I am not fine
Why what happened
Is there anything wrong?
I am very depressed about my online classes
Yes, We are in a hectic situation but we have to continue our studies
and be strong inside
There is nothing we can do about in this pandemic situation but to
study and pray
I feel too much preassure
Fave faith in Allah! Eveything will be ok
Everything will be fine soon
Yeap I will start praying to Allah that everything comes around
Im having problems with my Printer-Counter School Problem. Its supposed to be a multithreading application and runs fine so far. But when I running it the second or third time it wont work anymore.. No error message. Looks like Threads sleep forver or so. Also when I test it with a JUnit test it wont work. But sometimes it does... wich is already strange itself.
public class CounterPrinter {
public static void main(String[] args) throws InterruptedException {
if (args.length != 2) {
System.out.println("Usage: CounterPrinter <min> <max>");
System.exit(1);
}
Storage s = new Storage();
Printer d = new Printer(s, Integer.parseInt(args[1]));
Counter z = new Counter(s, Integer.parseInt(args[0]), Integer.parseInt(args[1]));
z.start();
d.start();
z.join();
d.join();
Thread.sleep(5000);
}
}
public class Printerextends Thread {
private Storage storage;
private Integer ende;
Printer(Storage s, Integer ende) {
this.storage = s;
this.ende = ende;
}
#Override
public void run() {
while (storage.hasValue()) {
try {
System.out.print(speicher.getValue(ende) + " ");
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Counter extends Thread {
private Storage speicher;
private int max, min;
Counter(Storages, int min, int max) {
this.storage = s;
this.max = max;
this.min = min;
}
#Override
public void run() {
for (int i = min; i <= max; i++) {
try {
storage.setValue(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Storage implements StorageIf {
private Integer wert;
private boolean hasValue = false;
#Override
public synchronized Integer getValue(Integer ende) throws InterruptedException {
if(wert.equals(ende)){
hasValue = false;
return wert;
}else {
while (!hasValue()) {
wait();
}
hasValue = false;
notifyAll();
return wert;
}
}
#Override
public synchronized void setValue(Integer wert) throws InterruptedException {
while (hasValue()){
wait();
}
hasValue = true;
this.wert = wert;
notifyAll();
}
#Override
public boolean hasValue() {
return hasValue;
}
}
Hope someone can spot a mistake I made :(
Thanks a lot!!!
The problem is that you conflate 2 states :
there is currently a value available
there will be no more values
Add an hasEnded() method to your Storage class, checking if the end value has been reached. Make sure to synchronize this method, as well as the hasValue() method. Synchronization needs to be done on both read and write access!
Then make Printer's while loop check hasEnded, rather than hasValue.
Finally : get rid of all the sleep() calls.
Your own answer, solving the problem with sleep, is not a real solution. A thread safe program does not depend on a computer's performance to function correctly.
z.start();
z.sleep(100);
d.start();
Putting a delay between starting the tow Threads solved the problem for me. My Computer was probably too fast down the road in Thread z before it even started Thread d. Thats why it hung itself up in 50% of the time.
Thanks to everyone tho :)
I have two threads. The first changes the value of variable Data. And second one print the value if its value has changed. I am trying to do that second thread just print each time that the variable's value changed, but I don't reach success. Someone can help me?
thread 1
class someservice{
volatile int data;
Boolean Flag = false;
public void mymethod(){
flag = true;
for (Integer i = 1; i < sheet.getRows(); i++) {
data = someMethod(); //this method when called return a new
//value
}
flag = false;
...
}
}
thread 2
Promise p = task {
try {
while (true) {
if (engineService.getFlag()) {
print(someservice.data);
}else{
break;
}
}
} catch(Throwable t) {
...
}
}
Since you mention Promises, I infer you are familiar with future/ promise in +C++11
in java there is a similar approach, with future callable...
public class HW5 {
public static void main(String[] argv) throws InterruptedException, ExecutionException {
FutureTask<Boolean> myFutureTask = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// implement the logic here and return true if everything was
// ok, false otherwise.
Thread.sleep(5000);
System.out.println("dddd");
return System.currentTimeMillis() % 2 == 0;
}
});
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(myFutureTask);
Boolean result = myFutureTask.get();
System.out.println("Done!");
}
}
FutureTask in a class that takes a callable which can return an Object after its job is done... in Order to execute the Future task you can use a Executor service, especifically calling the method execute, since you need to wait for the thread to do the job then is necessary that you call Future.get, that will basically blocks the main thread until the future is done, to verify the result, just read the variable result..
You could use the notify() and notifyAll() methods within thread. Check out this link: https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
public synchronized void guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while(!joy) {
try {
wait();
} catch (InterruptedException e) {}
}
System.out.println("Joy and efficiency have been achieved!");
}
public synchronized notifyJoy() {
joy = true;
notifyAll();
}
You have to look up more data about Concurrent programming,I can tell you now some basics,well,not so so basic,but i will do my best:
Here,you have a Monitor,it is an abstract concept,in resume,a Monitor is a
class with all it's
method using"syncronized"
as modifier, it means,
that only
one thread
can access
the method
at once.So,
in the
monitor is
the variable
that you
want to print,
and the"flag",
that tells you if
the variable
was modified.Finally,
you can
see the
most important thing,the"wait()"and"notify()"methods,
those method
stops the thread,or"play"
them again.
You ask
here in
the printValue() method, if your variable was changed, if the variable was'nt change, put the thead to sleep with the wait() method, and when the other
method changeValue() is executed, the value is modified, and the notify() method is called, waking up the thread, so, doing all this, you can guarantee three things:
Safety: meaning that the threads will do that you want
Absence of deadlock: meaning that the thread that is put to sleep, will be awake in the future.
Mutex: meaning that only one thread is executing the critical code, for example, the op. "++" is not atomic, is Subdivided inside in more the one action, create a local var, read the var, sum, and asign, so, if more than one thread are in the game, the value may not be consecutive, example:
i = 0;
i ++;
output: 1;
output: 2;
output: 3;
output: 5;
output: 4;
output: 7;
That could happen, and even so, that will happen in the next code, because there a more than one thread executing. Well, this is the way to program with several threads, more or less
public class Monitor {
private int value = 0;
public static boolean valueHasChanged = false;
public synchronized int changeValue(int newValue){
this.value = newValue;
Monitor.valueHasChanged = true;
this.notify();
return this.value + 1;
}
public synchronized void printValue(){
while(!Monitor.valueHasChanged){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(this.value);
Monitor.valueHasChanged = false;
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
Now the threads:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
And finally:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
int v = 0;
while(true){
this.ac.changeValue(v);
v++; // this sum is not secure, if you want to print an
// ascending order, the code is diferent, I will show in
// above.
}
}
Now, if you want an ordered print:
the monitor will look like:
public class Monitor {
private int value = 0;
public boolean valueHasChanged = false;
private boolean hasPrint = true;
public synchronized void changeValue(int newValue) {
this.value = newValue;
this.valueHasChanged = true;
this.notify();
}
public synchronized void changeValuePlusOne() {
while (!hasPrint) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.value++;
this.valueHasChanged = true;
this.hasPrint = false;
this.notifyAll();
}
public synchronized void printValue() {
while (!this.valueHasChanged) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.value);
this.valueHasChanged = false;
this.hasPrint = true;
this.notifyAll();
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
And the Threads:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.changeValuePlusOne();
}
}
}
The other Thread look equals:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
I tried using a volatile boolean to act as a flag to stop/start/restart the action in the thread, however it does not work. It just keeps on going forever and never terminates. Any help on how to properly do this or why my code does not work will be greatly appreciated. Thanks in advance.
public class thread {
public static int i = 0;
private static Thread print = null;
private static printThread runnable = null;
public static void main(String[] args) {
runnable = new printThread();
print = new Thread (runnable);
print.start();
System.out.println("Starting");
runnable.begin();
if(i > 5)
{
runnable.terminate();
}
i = 10;
runnable.begin();
if(i > 15)
{
runnable.terminate();
}
}
public static final void print()
{
System.out.println(i);
i++;
}
public static final class printThread implements Runnable {
private volatile boolean running = false;
public void terminate() {
running = false;
}
public void begin() {
running = true;
}
public boolean isRunning() {
return running;
}
public void run() {
while(true)
{
if(running)
{
print();
}
else
{
}
}
}
}
}
In your code while loop execution never ends. You could introduce 2 states: terminated and waiting to simulate threads start/pause/restart/stop. However, even if you pause the Thread it will be running, just different branch of code will be executed inside while loop.
Please, see the code snippet below
public static final class printThread implements Runnable {
private volatile boolean waiting = false;
private volatile boolean terminated = false;
public void terminate() {
terminated = true;
}
public void pause() {
waiting = true;
}
public void restart() {
waiting = false;
}
public void run() {
while(!terminated) {
if(waiting) {
//the thread is paused
} else {
//the thread is running
}
}
}
}
however it does not work. It just keeps on going forever and never terminates.
In your run() method of your thread, you aren't watching for the value of your volatile boolean running field. It probably should be something like:
public void run() {
while(!running) {
print();
// you might want a short Thread.sleep(10); here to stop the spinning
}
}
However, as #Anton points out, once your thread terminates, it can't be restarted without some other flag. See his answer.
Also, you are sharing i between the main thread and the your printing thread. That also needs to be volatile so it can be properly shared. Since you are incrementing it in multiple threads, you should use an AtomicInteger for that.
public static AtomicInteger i = new AtomicInteger();
...
if (i.get() > 5) ...
...
i.set(10);
...
i.incrementAndGet();
Couple of other comments:
Be careful of static fields. print and runnable should be defined only inside of the main(...) method to restrict access.
Classes should begin with an uppercase letter so it should be PrintThread.
Actually, because PrintThread isn't a thread, it should be PrintRunnable or maybe even better, Printer.