我需要一个一次只执行一个任务的线程池,当一个任务调用一个特殊方法时(我们称之为checkpoint
或yield
),然后:
我的任务大部分时间都在等待来自套接字的数据,因此Thread.setPriority()
不会这样做。
现在我写了一个可能包装的东西:
static final int READ_AHEAD_NUM = 5;
public String getFile(int fileId) {
ArrayList<String> urls = new ArrayList<String>(READ_AHEAD_NUM);
MyDownloadJob[] jobs = new MyDownloadJob[READ_AHEAD_NUM];
for (int i = 0; i < READ_AHEAD_NUM; i++) {
urls.add("http://.../" + (fileId++));
}
// reprioritize and cancel unneeded jobs
for (MyDownloadJob job : scheduler.getJobs()) {
int index = urls.indexOf(job.getUrl());
if (index == -1) {
job.cancel();
} else {
jobs[index] = job;
job.setPriority(index);
}
}
MyDownloadJob job;
// create missing jobs
for (int index = 0; index < READ_AHEAD_NUM; index++) {
if (jobs[index] == null) {
jobs[index] = job = scheduler.addJob(new MyDownloadJobImpl(urls.get(index)));
job.setPriority(index);
}
}
// wait 1st job
job = jobs[0];
job.join();
return job.getPath();
}
static abstract class MyDownloadJob extends Job {
public abstract String getPath();
public abstract String getUrl();
private void checkpoint(int workAmount) throws Exception {
if (super.yieldAndTestCancel(workAmount))
throw new Exception("cancelled");
}
@Override
public Object call() throws Exception {
checkpoint(0);
FileOutputStream fos = new FileOutputStream(getPath());
InputStream in = MyUtils.openConnection(getUrl());
checkpoint(0);
byte[] buffer = new byte[512];
int len;
while ((len = in.read(buffer)) != -1) {
checkpoint(len);
fos.write(buffer, 0, len);
}
for(;;) {
break;
}
in.close();
fos.close();
return null;
}
}
答案 0 :(得分:0)
我建议使用尽可能多的线程的线程池。然后,在你的worker中使用所有线程共有的信号量,在via外部创建 final Semaphore threadExecution = new Semaphore(1)
在内部,您可以通过该信号量上的aquire()和release()来控制执行。
答案 1 :(得分:0)
我看到两种方法:
请注意,选择作业的算法(通过某个优先级的等待时间)完全独立,因此应该有一种优先级队列。