私は単純なビデオ マニピュレータを作成しようとしているので、1 秒に数回、現在のフレームを処理するために新しいスレッド (現在 Runnable を実装している) を開始する必要がありますが、各スレッドが終了するまでにかかる時間の保証はありません。一度に実行できるスレッドの数をコンピューター上のプロセッサーの数に制限したい:
Runtime runtime = Runtime.getRuntime();
int nP = runtime.availableProcessors();
ただし、フレームがドロップされないように、作成されたすべてのスレッドが順番に実行されることを保証する必要があります。
また、ユーザーがジョブをキャンセルしたときに実行するために残っているスレッドの数に基づいて、処理が完了するまでにかかる時間をユーザーに示して、予告編のないビデオ ファイルになってしまわないようにしたいと思います。
これは、futureTask、Exector、または ExecutorService の任意の組み合わせを使用して可能でしょうか?
ありがとう。
編集:
こんにちは皆さん、申し訳ありません。私が実際にやろうとしているのは、フレームを取得し、画像操作を実行してから、編集した映像を新しいファイルに保存することです。現時点では、再生中にこれを行っているため、タイマーによって呼び出されたときに各フレームが操作され、タイマーはスレッドを起動して画像をできるだけ早く処理しますが、今回行われる操作の数によって異なります。
次に、処理が間隔よりも長くかかる場合、最大効率的な数のスレッドのみが処理に使用され、この制限に達した後に作成されたスレッドは引き続き処理され、ドロップまたはガベージ コレクションされないことを確認したいと考えていました。 .
最初の 3 つのコメントを読むと、これはおそらく効率の悪い方法であることがわかります。UI の応答性を維持するためだけに 1 つのスレッドを使用するとうまくいくと思いますが、スレッドに画像を追加し続ける方法がわかりません。巨大なリストを使用せずに処理します。私はそれが次のようなものになると仮定しています:
メインクラスでは:
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;
}
}
}
これは、画像処理が単純な場合はうまく機能しますが、もう少し複雑になると、すぐに数十の同時スレッドが実行しようとすることに遭遇します。フレームごとに書き込み時間が指定されているため、フレームを順不同で書き込むと正しい場所に配置されると思うため、この場合の順序が特に重要かどうかはわかりませんが、これにはテストが必要です。