0

In my application I have two classes that implements two different methods of processing a file.

Now I need I to add a boolean variable called isProcessing, that would be set to true everytime one of those two classes start processing a file. When processing is finished, it should go back to false.

And everytime when class X attempts to process a file it should check if class Y isn't processing at this time.

How to implement this without declaring a top level static global variable?

Bobzone
  • 276
  • 2
  • 12

2 Answers2

1

Well there are many ways... But why not using static ?


You can have one public class with a global variable isProcessing which has two nested classes X and Y so both can see the variable . Although if you are playing with multiple Threads then you need to also synchronize the variable....

public class Connector{

private volatile boolean isProcessing; //i am using volatile in case you have Threads but you need to further improve it.


  protected class X{

      public X(){ ... }

  }


  protected class Y{

   public Y(){....}

  }

}

Further links:

Java share a variable between two threads

http://java-tweets.blogspot.gr/2012/01/difference-between-volatile-and.html

http://javarevisited.blogspot.gr/2011/04/synchronization-in-java-synchronized.html


Highly reccomend to read the answer from here also:

What is the use of a private static variable in Java?

Community
  • 1
  • 1
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
  • I thought static variables are a terrible antipattern. – Bobzone Dec 01 '16 at 21:01
  • @Bobzone Sometimes are very useful . Imagine if you want to share a variable between a lot of classes ... Although for everything there are multiple ways to achieve it.. – GOXR3PLUS Dec 01 '16 at 21:03
1

Mutual exclusion

One way to do it would be using a locking object, a mutex, shared between your processing classes.

public static void main(String[] args) {

    ProcessingMutex mutex = new ProcessingMutex();

    Processor fileProcessorOne = new ProcessorOne(mutex);
    Processor fileProcessorTwo = new ProcessorTwo(mutex);

    // start threads and do your stuff

}

The mutex object would contain some logic to prevent one thread overriding the other threads lock:

public class ProcessingMutex {

    private Object processor = null;

    public boolean processing() {
        return processor != null;
    }

    public synchronized void start(Object p) {
        if (processor == null) {
            processor = p;
        } else {
            throw new IllegalStateException("Already processing!");
        }
    }

    public synchronized void finished(Object p) {
        if (processor == p) {
            processor = null;
        } else {
            // Optional: throw new IllegalStateException("Cannot reset other processors flag!");
        }
    }

}

Since they share the locking mechanism I derived the two processor classes from the same parent which implements the locking:

public abstract class Processor /* extends Runnable? */ {
    private final ProcessingMutex mutex;

    public Processor(ProcessingMutex mutex) {
        this.mutex = mutex;
    }

    public void processFile() {
        if (getLock()) {
            try {
                doProcess();
            } finally {
                // make sure to release lock -> finally
                releaseLock();
            }
        }
    }

    protected abstract void doProcess();

    private boolean getLock() {
        // query and set mutex in synchronized block to prevent interference with other thread
        synchronized (mutex) {
            if (!mutex.processing()) {
                mutex.start(this);
            }
        }
        return false;
    }

    private void releaseLock() {
        mutex.finished(this);
    }

}

public class ProcessorOne extends Processor {

    public ProcessorOne(ProcessingMutex mutex) {
        super(mutex);
    }

    @Override
    protected void doProcess() {
        // TODO add file processing algorithm one
    }

}

public class ProcessorTwo extends Processor {

    public ProcessorTwo(ProcessingMutex mutex) {
        super(mutex);
    }

    @Override
    protected void doProcess() {
        // TODO add file processing algorithm two
    }

}

Disclaimer: Please note, that this is only a very basic (late night) version to demonstrate my thoughts. It's has to be hardened in matters of thread-safety depending on the needs of your application.

Edit:

java.util.concurrent

You could of course use one of the Lock objects provided by Java (see java.util.concurrent API doc) as suggested in this other answer: https://stackoverflow.com/a/3493788/4791599

Community
  • 1
  • 1
Markus Mitterauer
  • 1,560
  • 1
  • 14
  • 28