Skip to content

Instantly share code, notes, and snippets.

@martin640
Last active February 23, 2019 10:44
Show Gist options
  • Save martin640/4fe5cd6221233dd82230c8818ea92d95 to your computer and use it in GitHub Desktop.
Save martin640/4fe5cd6221233dd82230c8818ea92d95 to your computer and use it in GitHub Desktop.
Simple looper for multiple synchronized operations in Java
package sk.gocrafterlp.networkconnections.handler;
import java.util.ArrayList;
import java.util.List;
public class LooperCompat {
private final List<Message> messageQueue;
private boolean running, exiting;
private Thread thread;
public LooperCompat() {
messageQueue = new ArrayList<>();
running = true;
thread = new Thread(new Runnable() {
@Override
public void run() {
while (running) {
loop();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
private void loop() {
Message message = null;
MessageGetter: synchronized (messageQueue) {
if (exiting && messageQueue.isEmpty()) {
running = false;
return;
}
for (int i = 0; i < messageQueue.size(); i++) {
Message next = messageQueue.get(i);
if (exiting) {
if (next.time > 0) { // cancel delayed message
messageQueue.remove(i);
return;
}
}
if (next.time == 0 || System.currentTimeMillis() >= next.time) {
message = next;
break MessageGetter;
}
}
}
if (message == null) return;
Runnable runnable = message.getRunnable();
Object tag = message.getTag();
if (runnable != null) runnable.run();
synchronized (messageQueue) {
messageQueue.remove(message);
}
}
/**
* Method will move looper into exiting state so all instant messages will be finished
*/
public void stop() {
exiting = true;
}
public boolean postDelayed(Runnable runnable, long delay) {
if (delay < 0) throw new IllegalArgumentException("Negative delay");
if (exiting) return false;
synchronized (messageQueue) {
Message message = new Message(runnable, null);
message.time = System.currentTimeMillis() + delay;
messageQueue.add(message);
}
return true;
}
public boolean post(Runnable runnable) {
if (exiting) return false;
synchronized (messageQueue) {
messageQueue.add(new Message(runnable, null));
}
return true;
}
}
package sk.gocrafterlp.networkconnections.handler;
class Message {
Runnable runnable;
Object tag;
long time;
Message(Runnable runnable, Object tag) {
this.runnable = runnable;
this.tag = tag;
}
Runnable getRunnable() {
return runnable;
}
Object getTag() {
return tag;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment