I am trying to understand concurrency for part of an assignment I'm doing. I think I've got the basics done, but I'm getting stuck in the nuances of my usecase.
I apologize in advance if I haven't mastered the art of the question yet.
Basic idea:
I have a class, of which a few objects are instantiated as representations of parts of a houses and their only main function is to operate(). The catch is that when "Bell" operates, I want the others to wait(). My while statement is based on a bell toggle (boolean). If it is on - wait(), if not, carry on. It seems when running this program, I'm starving the other threaded objects for the sake "Bell".
Any thoughts on where I've gone wrong?
import java.util.ArrayList;
class Test extends Thread {
static int number = 0;
private static final int TIMES = 30;
private static boolean bellstatus = false;
private String name;
private int val;
Test(String y,int x) {
number = number +1;
val = x;
name = new String(y);
}
public void run() { // overrides default run()
for (int i=val; i>0; i--){
System.out.println(name+" run() : " + i);
operate();
}
}
public synchronized void operate(){
System.out.println(name+ " operating");
while(bellstatus){
try{
System.out.println("Bell is ringing");
wait();}catch(InterruptedException e){}
}
if(name.equals("Bell")){
try{
System.out.println("Bell working");
bellstatus = true;
Thread.sleep(500);
Thread.yield();}catch(InterruptedException e){}
bellstatus = false;
notifyAll();
System.err.println("Bell is done");
}
if(name.equals("Door")){
try{
System.out.println("Door working");
Thread.sleep(500);}catch(InterruptedException e){}
}
if(name.equals("Window")){
try{
System.out.println("Window working");
Thread.sleep(500);}catch(InterruptedException e){}
}
}
public static void main(String arg[]) {
ArrayList<Test> example = new ArrayList();
Test a = new Test("Bell",20);
Test b = new Test("Door",20);
Test c = new Test("Window",20);// create thread
example.add(a);
example.add(b);
example.add(c);
System.out.println("Number of objects: "+a.number);
for(int i = 0;i<example.size();i++)
example.get(i).start();
// start thread run
}
}
Use just one thread and a queue of runnables. An executor with just one thread will queue your tasks until the one running is done https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
Please don't use Raw Types (you could use the diamond operator <>). Then, if I understand your question, one possible solution is to use a ReentrantLock like,
static class Test extends Thread {
static int number = 0;
private static Lock lock = new ReentrantLock();
private String name;
private int val;
Test(String y, int x) {
number = number + 1;
val = x;
name = new String(y);
}
public void run() {
for (int i = val; i > 0; i--) {
System.out.println(name + " run() : " + i);
operate();
}
}
public synchronized void operate() {
System.out.printf("%s operating%n", name);
lock.lock();
try {
System.out.printf("%s working%n", name);
Thread.sleep(500);
System.out.printf("%s done%n", name);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String arg[]) {
List<Test> example = new ArrayList<>();
Test a = new Test("Bell", 20);
Test b = new Test("Door", 20);
Test c = new Test("Window", 20);// create thread
example.add(a);
example.add(b);
example.add(c);
System.out.println("Number of objects: " + a.number);
for (int i = 0; i < example.size(); i++) {
example.get(i).start();
}
// start thread run
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With