Stopping and resuming infinite loop on key input - java

Let's say we have an infinite loop, and we want to put it to sleep for a while, and then resume it. Instead of having a set time, we resume it when we press a key.
For example, in Java we could have:
while(true){
doSomething();
}
Now, we could make this interruptable in many ways. We want to interrupt it on a key press, so we will have:
boolean running = true;
...
this.addKeyListener(this);
...
#override
public void keyPressed(KeyEvent e){
running = false;
}
And then run a method (let's say run), which contains:
while(running){
doSomething();
}
But then we'd meet one problem: resuming.
So we take the keyPressed method, and change it's body to:
running = !running;
if(running){
run();
}
There is just one problem here: the KeyListener won't do anything until the run method is finished. I've tried using threads, where we would have:
private class Runner implements Runnable {
#Override
public void run() {
while (running) {
doSomething();
}
}
}
and in keyPressed:
if(running){
runner.wait();
}else{
runner.notify();
runner.run();
}
running = !running;
but in my actual code the doSomething method is code that can't be interrupted (because it handles output to the screen), so thread.wait() can never be called (it will throw exceptions all the time and not actually wait).
So then, to summarize: How does one stop and resume looping something at will using key input in Java?

wait and notify are intended to be called from different threads. As the name implies, wait should be called in the thread which is paused and waiting to be notified that a condition has changed:
private final Object keyPressMonitor = new Object();
private boolean running = true;
private Runnable gameLoop = new Runnable() {
#Override
public void run() {
try {
synchronized (keyPressMonitor) {
while (true) {
while (!running) {
keyPressMonitor.wait();
}
doSomething();
}
}
} catch (InterruptedException e) {
logger.log(Level.INFO,
"Interrupted; cleaning up and exiting.", e);
}
}
};
The other thread, presumably the AWT Event Dispatch Thread which is where your KeyListener (or Action invoked by an ActionMap/InputMap binding) is called, would notify the looping thread that the proper key has been pressed or released:
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == theKeyICareAbout) {
synchronized (keyPressMonitor) {
running = true;
keyPressMonitor.notifyAll();
}
}
}
public void keyReleased(KeyEvent event) {
if (event.getKeyCode() == theKeyICareAbout) {
synchronized (keyPressMonitor) {
running = false;
keyPressMonitor.notifyAll();
}
}
}

You can use Semaphore for these purposes:
private static class Runner implements Runnable {
private final AtomicInteger permits = new AtomicInteger(0);
private final Semaphore semaphore = new Semaphore(1, true);
private volatile boolean running;
public void putToSleep() {
semaphore.acquireUninterruptibly();
}
public void resume() {
semaphore.release(permits.getAndSet(0));
}
#Override
public void run() {
while (running) {
semaphore.acquireUninterruptibly(Integer.MAX_VALUE);
semaphore.release(Integer.MAX_VALUE);
doSomething();
}
}
private void doSomething() {
//...
}
}

Related

Why stopping a SwingWorker does stop it immediately?

I'm using a SwingWorker to execute some repeatable tasks in background.
This is my Class:
public class CMyThread {
private SwingWorker<Object, Void> taskWorker;
public volatile boolean threadDone = false;
public CMyThread() {
}
#Override
public void stop() {
taskWorker.cancel(true);
}
#Override
public void start() {
taskWorker = new SwingWorker<Object, Void>() {
#Override
public Object doInBackground() {
while (!isCancelled()) {
// SOMETHING TIMECONSUMING THAT NEEDS TO BE DONE REPEATEDLY
CUtils.sleep(10000);
}
threadDone = true;
return null;
}
#Override
public void done() {
}
};
taskWorker.execute();
}
public void waitThreadToGentlyFinish() { // called when we call destroy() on the servlet
while (!threadDone) {
System.out.print("#");
CUtils.sleep(200);
}
}
}
And this is called this way:
CMyThread myThread = new CMyThread();
myThread.start();
Now, at one point I want to gently stop the thread.
So I call
myThread.stop();
myThread.waitThreadToGentlyFinish();
I'm expecting that the currently running [ACTION] is going to take time to finish, then only it will exit the loop and set the flag 'threadDone' to true. but what I actually see is that it exits the loop immediately and I never see any '#' characters displayed.
There is obviously something wrong in my code but I can't see the obvious.
Any idea guys ?

How to put a infinite task(Runnable) give up for a while

As title, I want to make a Runnable rest for a while, then another task in ExecutorService has the chance to do its task.
Here the assumption:
public class Sample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.execute(new Task());
}
}}
public class Task implements Runnable{
#Override
public void run() {
while(true) {
doTask();
// how to make this task give up for a while
// then other tasks in ExecutetorService have
// change to run like Thread.yield()?
// Thread.yield();
}
}
public void doTask() {
// assume it take some seconds to finish
}}
Thanks in advance.
ThreadPool will have maximum 5 Threads as per your construction and when you do Thread.sleep() or Thread.yield (to reduce it's priority but not anything guaranteed), it's making ThreadPool's thread to go sleep not your tasks so pending tasks from Queue won't get chance.
As an alternative option, you can make a queue which will hold half executed Tasks, you put tasks in this queue so you can execute after some time.
As I mentioned in my comment your tasks (Runnable/Callable) need to implement themselves some logic that can check to pause or resume. There are various ways to do that.
Also there is an example PausableThreadPoolExecutorin doc itself. The following code is taken from doc only:
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
private boolean isPaused;
private ReentrantLock pauseLock = new ReentrantLock();
private Condition unpaused = pauseLock.newCondition();
public PausableThreadPoolExecutor(...) { super(...); }
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
pauseLock.lock();
try {
while (isPaused) unpaused.await();
} catch(InterruptedException ie) {
t.interrupt();
} finally {
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused = true;
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused = false;
unpaused.signalAll();
} finally {
pauseLock.unlock();
}
}
}
The above code makes use of ReentrantLock to pause and resume.

Pause new threads from executing using ExectuorService

I would like to pause the new tasks from executing. The example provided in the Official Documentation seems to be stopping the currently executed tasks as well (though I am wondering how it does that without interrupting the thread).
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
private boolean isPaused;
private ReentrantLock pauseLock = new ReentrantLock();
private Condition unpaused = pauseLock.newCondition();
public PausableThreadPoolExecutor(...) { super(...); }
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
pauseLock.lock();
try {
while (isPaused) unpaused.await();
} catch (InterruptedException ie) {
t.interrupt();
} finally {
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused = true;
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused = false;
unpaused.signalAll();
} finally {
pauseLock.unlock();
}
}
}
Wrapping the Runnable interface could be easier for this, then you don't have to make your own ThreadPool.
public abstract class PausableRunnable implements Runnable{
private final object _monitor;
public PausableRunnable(object monitor){
_monitor = monitor;
}
#Override
public void Run(){
WaitForNotify();
}
public void WaitForNotify(){
synchronized(_monitor){
while(!done){
_monitor.wait();
}
}
doWork();
}
public abstract void doWork();
}
This could pause new threads easily. Pausing a running thread is a different task, I think this is what you meant. The biggest problem with my solution is if you already want to inherit from something, but it's a starting point
The question was incorrect. The PausablableThreadPoolExecutor does not stop the currently executed thread. Apologies for the incorrect question.

AbstractQueuedSynchronizer.acquireShared waits infinitely even that waiting condition has changed

I wrote a simple class that uses AbstractQueuedSynchronizer. I wrote a class that represents a "Gate", that can be passed if open, or is blocking if closed. Here is the code:
public class GateBlocking {
final class Sync extends AbstractQueuedSynchronizer {
public Sync() {
setState(0);
}
#Override
protected int tryAcquireShared(int ignored) {
return getState() == 1 ? 1 : -1;
}
public void reset(int newState) {
setState(newState);
}
};
private Sync sync = new Sync();
public void open() {
sync.reset(1);
}
public void close() {
sync.reset(0);
}
public void pass() throws InterruptedException {
sync.acquireShared(1);
}
};
Unfortunately, if a thread blocks on pass method because gate is closed and some other thread opens the gate in meantime, the blocked one doesn't get interrupted - It blocks infinitely.
Here is a test that shows it:
public class GateBlockingTest {
#Test
public void parallelPassClosedAndOpenGate() throws Exception{
final GateBlocking g = new GateBlocking();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
g.open();
} catch (InterruptedException e) {
}
}
});
t.start();
g.pass();
}
}
Please help, what should I change to make the gate passing thread acquire the lock successfully.
It looks like setState() only changes the state, but doesn't notify blocked threads about the change.
Therefore you should use acquire/release methods instead:
#Override
protected boolean tryReleaseShared(int ignored) {
setState(1);
return true;
}
...
public void open() {
sync.releaseShared(1);
}
So, overall workflow of AbstractQueuedSynchronizer looks like follows:
Clients call public acquire/release methods
These methods arrange all synchronization functionality and delegate actual locking policy to protected try*() methods
You define your locking policy in protected try*() methods using getState()/setState()/compareAndSetState()

Create a java thread that runs on a timer but can be awaken at any time

I would like to create a class that runs something (a runnable) at regular intervals but that can be awaken when needed. If I could encapsulate the whole thing I would like to expose the following methods:
public class SomeService implements Runnable {
public run() {
// the code to run at every interval
}
public static void start() { }
public static void wakeup() { }
public static void shutdown() { }
}
Somehow I've gotten this far. But I'm not sure if this is the correct approach.
public class SomeService implements Runnable {
private static SomeService service;
private static Thread thread;
static {
start();
}
private boolean running = true;
private SomeService() {
}
public void run() {
while (running) {
try {
// do what needs to be done
// perhaps peeking at a blocking queue
// or checking for records in a database
// trying to be independent of the communication
System.out.println("what needs to be done");
// wait for 15 seconds or until notify
synchronized (thread) {
try {
thread.wait(15000);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void start() {
System.out.println("start");
service = new SomeService();
thread = new Thread(service);
thread.setDaemon(true);
thread.start();
}
public static void wakeup() {
synchronized (thread) {
thread.notify();
}
}
public static void shutdown() {
synchronized (thread) {
service.running = false;
thread.interrupt();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("shutdown");
}
public static void main(String[] args) throws IOException {
SomeService.wakeup();
System.in.read();
SomeService.wakeup();
System.in.read();
SomeService.shutdown();
}
}
I'm concerned that the variables should be declared volatile. And also concerned that I should check in the "what needs to be done part" for thread.isInterrupted(). Does this seem like the right approach? Should I translate this to executors? How can I force a run on a scheduled executor?
EDIT
After experimenting with the executor, it seems that this approach seems reasonable. What do you think?
public class SomeExecutorService implements Runnable {
private static final SomeExecutorService runner
= new SomeExecutorService();
private static final ScheduledExecutorService executor
= Executors.newSingleThreadScheduledExecutor();
// properties
ScheduledFuture<?> scheduled = null;
// constructors
private SomeExecutorService() {
}
// methods
public void schedule(int seconds) {
scheduled = executor.schedule(runner, seconds, TimeUnit.SECONDS);
}
public void force() {
if (scheduled.cancel(false)) {
schedule(0);
}
}
public void run() {
try {
_logger.trace("doing what is needed");
} catch (Exception e) {
_logger.error("unexpected exception", e);
} finally {
schedule(DELAY_SECONDS);
}
}
// static methods
public static void initialize() {
runner.schedule(0);
}
public static void wakeup() {
runner.force();
}
public static void destroy() {
executor.shutdownNow();
}
}
For starters - you probably don't want to implement Runnable yourself; you should take in a Runnable. You should only implement Runnable if you expect your class to be passed to others to execute.
Why not just wrap a ScheduledExecutorService? Here's a quick (very poor, but ought to be functional) implementation.
public class PokeableService {
private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
private final Runnable codeToRun;
public PokeableService (Runnable toRun, long delay, long interval, TimeUnit units) {
codeToRun = toRun;
service.scheduleAtFixedRate(toRun, delay, interval, units);
}
public void poke () {
service.execute(codeToRun);
}
}
The variables do not need to be volatile since they are read and modified in a synchronized block.
You should use a different object for the lock then the thread, since the Thread class does it's own synchronization.
I would recommend using a single threaded ScheduledExecutorService and remove sleeping. Then if you want to run the task during the current sleep period, you can submit it to the executor again for a single time run. Just use the execute or submit methods in ExecutorService which ScheduledExecutorService extends.
About checking for isInterrupted, you should do this if the do work portion can take a lot of time, can be cancelled in the middle, and is not calling methods that block and will throw an interrupted exception any ways.
Using wait/notify should be a more efficient method. I also agree with the suggestion that using 'volatile' is not necessary and synchronizing on an alternative object would be wise to avoid conflicts.
A few other suggestions:
Start the thread elsewhere, starting from a static block is not good practice
Putting the execute logic in an "execute()" method or similar would be desirable
This code implements the above suggestions. Note also that there is only the one thread performing the SomeService execution logic and that it will occur INTERVAL milliseconds after the time it last completed. You should not get duplicate executions after a manually triggered wakeUp() call.
public class SomeService implements Runnable {
private static final INTERVAL = 15 * 1000;
private Object svcSynchronizer = new Object();
private boolean running = true;
private SomeService() {
}
public void run() {
while (running) {
try {
// do what needs to be done
// perhaps peeking at a blocking queue
// or checking for records in a database
// trying to be independent of the communication
System.out.println("what needs to be done");
// wait for 15 seconds or until notify
try {
svcSynchronizer.wait(INTERVAL);
} catch (InterruptedException e) {
// ignore interruptions
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void wakeUp() {
svcSynchronizer.notifyAll();
}
public void shutdown() {
running = false;
svcSynchronizer.notifyAll();
}
}

Categories

Resources