问题
We require a piece of code to control a thread. For example, use three buttons like start, stop and pause, press one of them and perform the action against it. Like press start then start the thread, press stop actually stops thread and pause perform pause action respectively.
回答1:
Starting a thread is simple with Thread.start()
. Stopping a thread can be as simple as setting a flag that is checked asychronously in the run method, but may need to include a call to Thread.interrupt()
. Pausing a thread is more problematic, but could also be done using a flag that cauases the run method to yield instead of process. Here is some (untested) code:
class MyThread extends Thread {
private final static int STATE_RUN = 0, STATE_PAUSE = 2, STATE_STOP = 3;
private int _state;
MyThread() {
_state = STATE_RUN;
}
public void run() {
int stateTemp;
synchronized(this) {
stateTemp = _state;
}
while (stateTemp != STATE_STOP) {
switch (stateTemp) {
case STATE_RUN:
// perform processing
break;
case STATE_PAUSE:
yield();
break;
}
synchronized(this) {
stateTemp = _state;
}
}
// cleanup
}
public synchronized void stop() {
_state = STATE_STOP;
// may need to call interrupt() if the processing calls blocking methods.
}
public synchronized void pause() {
_state = STATE_PAUSE;
// may need to call interrupt() if the processing calls blocking methods.
// perhaps set priority very low with setPriority(MIN_PRIORITY);
}
public synchronized void unpause() {
_state = STATE_RUN;
// perhaps restore priority with setPriority(somePriority);
// may need to re-establish any blocked calls interrupted by pause()
}
}
As you can see it can quite quickly get complex depending on what you are doing in the thread.
回答2:
I would like to add on Richard's answer to address a few issues:
- Needless cycles when paused
- Needless extra cycle when state changed
yield()
used wherewait()
needed- Single instance
- Stopping the thread waits for the thread to finish
This is my altered code:
class MyThread extends Thread {
private final static int STATE_RUN = 0, STATE_PAUSE = 2, STATE_STOP = 3;
private int _state;
private static MyThread thread;
public static MyThread getInstance() {
if (thread == null || !thread.isAlive()) {
thread = new MyThread();
}
return thread;
}
private MyThread() {
_state = STATE_RUN;
}
public static void main(String[] args) {
MyThread t = MyThread.getInstance();
try {
t.start();
Thread.sleep(500);
t.pause();
Thread.sleep(500);
t.unpause();
Thread.sleep(500);
t.end();
} catch (InterruptedException e) {
// ignore; this is just an example
}
}
public void run() {
int i = 0;
while (_state != STATE_STOP) {
if (_state == STATE_PAUSE) {
System.out.println(this + " paused");
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
}
if (_state == STATE_STOP) {
break;
}
// this is where the actual processing happens
try {
// slow output down for this example
Thread.sleep(100);
} catch (InterruptedException e) {
// state change handled next cycle
}
System.out.println(this + " cycle " + i);
i++;
}
System.out.println(this + " finished");
// cleanup
}
public synchronized void end() {
_state = STATE_STOP;
try {
this.interrupt();
this.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void pause() {
_state = STATE_PAUSE;
}
public synchronized void unpause() {
_state = STATE_RUN;
synchronized (this) {
this.notify();
}
}
}
来源:https://stackoverflow.com/questions/3178129/start-and-stop-thread-control-through-button