Java threading, suspending multiple other threads while running

I am trying to understand the concurrency for a part of the job I am doing. I think I have the basics, but I am stuck with the nuances of my use.

I apologize in advance if I haven't mastered the art of asking yet.

Main idea:

I have a class from which several objects are created as representations of parts of houses, and their only main function is work (). The trick is that when Bell is running, I want the others to wait (). The my while statement is based on a call toggle (boolean). If it's on - wait (), if not, continue. It seems when I run this program I am starving for other streamed objects for Bell.

Any thoughts on where I went 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 
    
}
}
      

Run codeHide result


+3


source to share


3 answers


Use only one thread and a runnables queue. A single thread executor queues up your tasks until one of them is done https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html



+1


source


Please do not use Raw types (you can use a diamond operator <>

). Then, if I understand your question, one possible solution is to use ReentrantLock

, for example,



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
}

      

+1


source


The javadoc notifyAll

mentions:

Wakes up all threads that are waiting for this monitor object. A thread waits for a monitor object by calling one of the wait methods.

However, the method operate

synchronizes the instance of the thread object. Hence, notifyAll

it will not wake up threads that are waiting since each thread owns a different monitor and waits on that monitor.

One way to solve this problem is to synchronize on a shared lock:

...
static Object lock = new Object();
...

public void operate() {
    synchronized (lock) {

        System.out.println(name + " operating");

        while (bellstatus) {
            try {
                System.out.println("Bell is ringing");
                lock.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;
            lock.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) {
            }
        }
    }
}

      

0


source







All Articles