需要更有效的暂停循环方式 [英] More efficient way for pausing loop wanted
问题描述
是否可以重写此代码以更好地与处理器一起工作?我有一个类,它在一个单独的线程中以固定的周期执行一些任务.有时这个过程可以暂停和恢复.目前我正在使用暂停标志,它工作正常,但是当进程暂停时,以这种方式循环仍然加载处理器.可以解决这个问题吗?
Is it possible to rewrite this code for better working with processor? I have a class, which does some tasks with fixed periodicy in a separate thread. Sometimes this process can be paused and resumed. Currently I am using a flag for pausing, it works fine, but loop in this way still loads processor when process is paused. Is it possible to fix this?
private boolean mIsCanceled = false;
private boolean mIsPaused = true; // TODO more efficient for processor way of pausing is required
private final Thread mTimerThread = new Thread(new Runnable() {
@Override
public void run() {
while(!mIsCanceled){
try {
Thread.sleep(UPDATE_PERIOD);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!mIsPaused){
doStep();
}
}
}
});
public MyClass(){
mTimerThread.start();
}
private void pause(){
mIsPaused = true;
}
private void resume(){
mIsPaused = false;
}
private void doStep(){
// Some code
}
请提供我的代码的替代实现.
Please just provide alternative implementation of my code.
附言环境为Android OS 2.2+
P.S. The environment is Android OS 2.2+
推荐答案
可用的工具有:
wait
/notify
- 我们都在努力摆脱这个古老的系统.
wait
/notify
- we are all trying to get away from this archaic system.
Semaphore
s - 一旦你的线程抓住了它,你就保持它直到释放,所以再次抓住它不会阻塞.这意味着您不能在自己的线程中暂停.
Semaphore
s - once your thread has grabbed it you hold it until release so grabbing it again does not block. This means you cannot pause from within your own thread.
CyclicBarrier
- 每次使用时必须重新创建.
CyclicBarrier
- Must be created anew each time it is used.
ReadWriteLock
- 我的最爱.您可以根据需要暂停任意数量的线程,并且只有在所有线程都调用 resume
时才会继续.如果您愿意,您甚至可以暂停自己.
ReadWriteLock
- My favorite. You can have as many threads pausing you as you like and you will only resume when all of them have called resume
. You can even pause yourself if you wish.
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* PauseableThread is a Thread with pause/resume and cancel methods.
*
* The meat of the process must implement `step`.
*
* You can either extend this and implement `step` or use the factory.
*
* Note that I cannot extend Thread because my resume will clash with Thread's deprecated one.
*
* Usage: Either write a `Stepper` and run it in a `PausableThread` or extend `PausableThread` and call `blockIfPaused()` at appropriate points.
*/
public abstract class PauseableThread implements Runnable {
// The lock.
// We'll hold a read lock on it to pause the thread.
// The thread will momentarily grab a write lock on it to pause.
// This way you can have multiple pausers using normal locks.
private final ReadWriteLock pause = new ReentrantReadWriteLock();
// Flag to cancel the wholeprocess.
private volatile boolean cancelled = false;
// The exception that caused it to finish.
private Exception thrown = null;
@Override
// The core run mechanism.
public void run() {
try {
while (!cancelled) {
// Block here if we're paused.
blockIfPaused();
// Do my work.
step();
}
} catch (Exception ex) {
// Just fall out when exception is thrown.
thrown = ex;
}
}
// Block if pause has been called without a matching resume.
private void blockIfPaused() throws InterruptedException {
try {
// Grab a write lock. Will block if a read lock has been taken.
pause.writeLock().lockInterruptibly();
} finally {
// Release the lock immediately to avoid blocking when pause is called.
pause.writeLock().unlock();
}
}
// Pause the work. NB: MUST be balanced by a resume.
public void pause() {
// We can wait for a lock here.
pause.readLock().lock();
}
// Resume the work. NB: MUST be balanced by a pause.
public void resume() {
// Release the lock.
pause.readLock().unlock();
}
// Stop.
public void cancel() {
// Stop everything.
cancelled = true;
}
// start - like a thread.
public void start() {
// Wrap it in a thread.
new Thread(this).start();
}
// Get the exceptuion that was thrown to stop the thread or null if the thread was cancelled.
public Exception getThrown() {
return thrown;
}
// Create this method to do stuff.
// Calls to this method will stop when pause is called.
// Any thrown exception stops the whole process.
public abstract void step() throws Exception;
// Factory to wrap a Stepper in a PauseableThread
public static PauseableThread make(Stepper stepper) {
StepperThread pauseableStepper = new StepperThread(stepper);
// That's the thread they can pause/resume.
return pauseableStepper;
}
// One of these must be used.
public interface Stepper {
// A Stepper has a step method.
// Any exception thrown causes the enclosing thread to stop.
public void step() throws Exception;
}
// Holder for a Stepper.
private static class StepperThread extends PauseableThread {
private final Stepper stepper;
StepperThread(Stepper stepper) {
this.stepper = stepper;
}
@Override
public void step() throws Exception {
stepper.step();
}
}
// My test counter.
static int n = 0;
// Test/demo.
public static void main(String[] args) throws InterruptedException {
try {
// Simple stepper that just increments n.
Stepper s = new Stepper() {
@Override
public void step() throws Exception {
n += 1;
Thread.sleep(10);
}
};
PauseableThread t = PauseableThread.make(s);
// Start it up.
t.start();
Thread.sleep(1000);
t.pause();
System.out.println("Paused: " + n);
Thread.sleep(1000);
System.out.println("Resuminng: " + n);
t.resume();
Thread.sleep(1000);
t.cancel();
} catch (Exception e) {
}
}
}
代码修改为更通用.
这篇关于需要更有效的暂停循环方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!