我有一个队列,插入和处理新对象。为了处理我使用可以结束并且可以重新启动的单线程。
private Thread backgroundThread;
private final Queue<ImgData> queuedImgs = new LinkedList<>();
public void scheduleNewCodeImg(ImgData imgData) {
LOG.log(Level.INFO, "entering{0}", new Object[]{imgData});
queuedImgs.add(imgData);
}
public void createAndSetImgs() {
if (backgroundThread == null || !backgroundThread.isAlive()) {
LOG.log(Level.INFO, "starting thread proces for creating codeImgs");
backgroundThread = new Thread(new ExecutionThread(0, true) {
@Override
protected boolean process() {
if (!queuedImgs.isEmpty()) {
ImgData imgData = queuedImgs.poll();
if (imgData != null) {
saveImg(imgData);
return true;
}
}
return false;
}
}, "CodeImgOnS3CreatorThread");
backgroundThread.start();
}
}
private void saveImg(final ImgData imgData) {
//do smthng
}
我的runnable接口的实现提供了抽象process
方法,并反复检查有限量的迭代方法返回值。如果为true,则进程重置为从开始时开始:
public abstract class ExecutionThread implements Runnable {
private static final Logger LOG = Logger.getLogger(ExecutionThread.class.getName());
private final int baseDelayInSeconds;
private final boolean uniformDelayGrowth;
private static final int DEFAULT_DELAY_SECONDS = 5; // for 5 the calculated iterationDelays are 1,1,1,5,5,5,25,25,25
private static final int ITERATIONS_COUNT = 3;
private static final int STEPS_COUNT = 3;
public ExecutionThread() {
this.baseDelayInSeconds = DEFAULT_DELAY_SECONDS;
this.uniformDelayGrowth = false;
}
public ExecutionThread(int baseDelayInSeconds, boolean uniformDelayGrowth) {
this.baseDelayInSeconds = baseDelayInSeconds;
this.uniformDelayGrowth = uniformDelayGrowth;
}
@Override
public final void run() {
LOG.log(Level.INFO, "running new ExecutionThread");
int step = 0;
while (step < STEPS_COUNT) {
for (int iteration = 0; iteration < ITERATIONS_COUNT; iteration++) {
try {
if (this.baseDelayInSeconds > 0) {
if (uniformDelayGrowth) {
Thread.sleep(this.baseDelayInSeconds * 1000);
} else {
long iterationDelay = (long) Math.pow(this.baseDelayInSeconds, step) * 1000;
Thread.sleep(iterationDelay);
}
} else {
Thread.sleep(10); //minimal processing timeout to provide time for finishing tasks to end
}
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, "thread sleep was interrupted: ", ex);
}
if (process()) {
step = 0;
iteration = 0;
}
}
step++;
}
}
/**
*
* @return true if iterations should be reset from start, else false
*/
protected abstract boolean process();
}
用法如下(简化)
instance = new InstanceOfService();
instance.scheduleNewCodeImg(imgObj);
instance.createAndSetImgs();
我怀疑在最后一次迭代结束的那一刻,可能会有一些错误没有处理插入的项目。 我考虑过一些同步,但我不确定同步这两种方法会有所帮助,因为该过程在backgrounf线程中运行。 你能指点我怎么解决这个问题吗?