我正在尝试编写一个简单的视频操纵器,所以每秒几次我需要启动一个新线程(当前正在实现 Runnable)来处理当前帧,但我不能保证每个线程需要多长时间才能完成,因此我想要将一次可以运行的线程数限制为计算机上的处理器数:
Runtime runtime = Runtime.getRuntime();
int nP = runtime.availableProcessors();
但我需要保证创建的所有线程都按顺序运行,因此不会丢帧。
我还想根据用户取消作业时剩余运行的线程数向用户展示完成处理需要多长时间,这样他们就不会得到没有预告片的视频文件。
使用 futureTask、Execector 或 ExecutorService 的任意组合是否可以实现这一点?
谢谢。
编辑:
大家好,对不起,那是相当糟糕的措辞。所以我实际上想要做的是获取帧,执行一些图像处理,然后将编辑后的素材保存回一个新文件。目前我正在播放期间执行此操作,因此当计时器调用每个帧时都会对其进行操作,然后计时器会启动一个线程以尽快处理图像,但取决于这次操作的数量会有所不同。
然后我想确保如果处理时间长于仅使用最大有效线程数进行处理的时间间隔,并且在达到此限制后创建的任何线程仍然得到处理并且不会被丢弃或垃圾收集.
阅读了前 3 条评论后,我可以看到这可能是一种效率较低的方法,我想只有一个线程来保持 UI 响应会起作用,但我不确定如何继续将图像添加到线程中它可以在不使用大量列表的情况下进行处理。我假设它会是这样的:
在主课中:
Timer actionPerformed {
List.add(decodedImage);
}
在可运行类中:
run() {
while( timer.isRunning() ) {
if( runCount >= list.size()-1 ) {
try {
Thread.sleep(500);
} catch() {
/* Catchy stuff */
}
} else {
BufferedImage toProcess = list.get(runCount);
/* Do Processing here */
writeImageToStream();
list.remove(runCount);
runCount++;
}
}
}
这个对吗?
编辑2:
所以这就是我到目前为止所拥有的:
public class timerEncode {
private long startTime;
ActionListener goAction = new ActionListener() {
public void actionPerformed( ActionEvent evt ) {
BufferedImage decoded = getNextImage();
long write_time = System.nanoTime();
new doImages(decoded, write_time).run();
}
};
Timer goTimer = new Timer(40,goAction);
private BufferedImage getNextImage() {
/* Does inconsequential stuff to retrieve image from the stream*/
}
private void recBtnActionPerformed(java.awt.event.ActionEvent evt) {
startTime = System.nanoTime();
goTimer.start();
}
private class doImages implements Runnable {
final BufferedImage image;
final long write_time;
public doImages(BufferedImage image, long write_time) {
this.image = image;
this.write_time = write_time;
}
public void run() {
BufferedImage out = toXuggleType(image, BufferedImage.TYPE_3BYTE_BGR);
/* Other time consuming processy stuff goes here */
/* Encode the frame to a video stream */
writer.encodeVideo(0,out,write_time-startTime, TimeUnit.NANOSECONDS);
}
private BufferedImage toType(BufferedImage source, int type) {
if( source.getType() != type ) {
BufferedImage temp = new BufferedImage(source.getWidth(),source.getHeight(),type);
temp.getGraphics().drawImage(source, 0, 0, null);
source = temp;
}
return source;
}
}
}
当图像处理很简单时,这很好用,但是你很快就会遇到数十个并发线程试图做他们的事情,因为它变得有点复杂,因此我问如何限制并发线程数而不丢弃任何线程。我不确定在这种情况下顺序特别重要,因为我认为乱序写入帧会将它们放在正确的位置,因为每个帧都指定了写入时间,但这需要测试。