Java 1.4 synchronization: allow only one method instance (non-blocking)?

I have a class offering translation utilities. The translations themselves need to be reloaded every 30 minutes. I use Spring timer support. Basically, my class is as follows:

public interface Translator {
    public void loadTranslations();
    public String getTranslation(String key);
}

loadTranslations () can be quite long to run, so while it works, old translations are still available. This is done by downloading translations on a local map and simply changing the link when downloading all translations.

My problem: how can I make sure that when the thread is already downloading translations, the second one tries to start, it detects this and immediately returns without launching the second update.

The synchronized method will only queue the loads ... I'm still in Java 1.4, so there is no java.util.concurrent.

Thank you for your help!

+3
source share
4 answers

Use some form of locking mechanism to complete a task only if it is not already running. The acquisition of a blocking token should be a one-step process. Cm:

/**
 * @author McDowell
 */
public abstract class NonconcurrentTask implements Runnable {

    private boolean token = true;

    private synchronized boolean acquire() {
        boolean ret = token;
        token = false;
        return ret;
    }

    private synchronized void release() {
        token = true;
    }

    public final void run() {
        if (acquire()) {
            try {
                doTask();
            } finally {
                release();
            }
        }
    }

    protected abstract void doTask();

}

Test code that throws an exception if the task runs simultaneously:

public class Test {

    public static void main(String[] args) {
        final NonconcurrentTask shared = new NonconcurrentTask() {
            private boolean working = false;

            protected void doTask() {
                System.out.println("Working: "
                        + Thread.currentThread().getName());
                if (working) {
                    throw new IllegalStateException();
                }
                working = true;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                if (!working) {
                    throw new IllegalStateException();
                }
                working = false;
            }
        };

        Runnable taskWrapper = new Runnable() {
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    shared.run();
                }
            }
        };
        for (int i = 0; i < 100; i++) {
            new Thread(taskWrapper).start();
        }
    }

}
+3
source

.net( Java), - , , alrady. , , , / . , , , , . , . , / iunsetting , . , , .

: , . , ? , .

+1

, , ?

, , ?

0

, Singleton (gasp!), :

if (instance == null) {
  synchronized {
    if (instance == null) {
       instance = new SomeClass();
    }
  }
}

. , , , , ( ).

:

if (translationsNeedLoading()) {
  synchronized {
    if (translationsNeedLoading()) {
       loadTranslations();
    }
  }
}

UPDATE: this way of building a singlet will not work reliably under your JDK1.4. See here for an explanation . However, I think you will be fine in this scenario.

0
source

Source: https://habr.com/ru/post/1697704/


All Articles