Java 1.4 synchronization: only allow one instance of method to run (non blocking)?

后端 未结 4 963
眼角桃花
眼角桃花 2021-01-20 05:14

I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class lo

4条回答
  •  不思量自难忘°
    2021-01-20 05:34

    Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:

    /**
     * @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 will throw an exception if the task runs concurrently:

    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();
            }
        }
    
    }
    

提交回复
热议问题