Интересная вещь, которую я узнал о Стеке по сравнению с Выделением "кучи" на процессоре Xbox 360 Xenon, который может также относиться к другим многоядерным системам, состоит в том, что выделение на "куче" заставляет Критический Раздел вводиться для остановки всех других ядер так, чтобы выделение не конфликтовало. Таким образом, в жестком цикле, Выделение Стека было способом пойти для фиксированных размерных массивов, поскольку это предотвратило остановы.
Это может быть другим ускорением, чтобы рассмотреть, кодируете ли Вы для multicore/multiproc, в том Вашем стеке выделение только будет просматриваемым ядром, выполняющим Вашу ограниченную по объему функцию, и это не будет влиять ни на какие другие ядра/Центральные процессоры.
Here's a fairly basic implementation that fires PropertyChangeEvent
s when additional bytes are read. Some caveats:
mark
or reset
operations, although these would be easy to add.Code:
public class ProgressInputStream extends FilterInputStream {
private final PropertyChangeSupport propertyChangeSupport;
private final long maxNumBytes;
private volatile long totalNumBytesRead;
public ProgressInputStream(InputStream in, long maxNumBytes) {
super(in);
this.propertyChangeSupport = new PropertyChangeSupport(this);
this.maxNumBytes = maxNumBytes;
}
public long getMaxNumBytes() {
return maxNumBytes;
}
public long getTotalNumBytesRead() {
return totalNumBytesRead;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
@Override
public int read() throws IOException {
int b = super.read();
updateProgress(1);
return b;
}
@Override
public int read(byte[] b) throws IOException {
return (int)updateProgress(super.read(b));
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return (int)updateProgress(super.read(b, off, len));
}
@Override
public long skip(long n) throws IOException {
return updateProgress(super.skip(n));
}
@Override
public void mark(int readlimit) {
throw new UnsupportedOperationException();
}
@Override
public void reset() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean markSupported() {
return false;
}
private long updateProgress(long numBytesRead) {
if (numBytesRead > 0) {
long oldTotalNumBytesRead = this.totalNumBytesRead;
this.totalNumBytesRead += numBytesRead;
propertyChangeSupport.firePropertyChange("totalNumBytesRead", oldTotalNumBytesRead, this.totalNumBytesRead);
}
return numBytesRead;
}
}
If you’re building a GUI application there’s always ProgressMonitorInputStream. If there’s no GUI involved wrapping an InputStream
in the way you describe is a no-brainer and takes less time than posting a question here.
Пакет Guava com.google.common.io
может вам немного помочь. Следующее не скомпилировано и не протестировано, но должно направить вас на верный путь.
long total = file1.length();
long progress = 0;
final OutputStream out = new FileOutputStream(file2);
boolean success = false;
try {
ByteStreams.readBytes(Files.newInputStreamSupplier(file1),
new ByteProcessor<Void>() {
public boolean processBytes(byte[] buffer, int offset, int length)
throws IOException {
out.write(buffer, offset, length);
progress += length;
updateProgressBar((double) progress / total);
// or only update it periodically, if you prefer
}
public Void getResult() {
return null;
}
});
success = true;
} finally {
Closeables.close(out, !success);
}
Это может показаться большим количеством кода, но я считаю, что это меньшее, что вам сойдет с рук. (обратите внимание, что в других ответах на этот вопрос не приводятся полные примеры кода, поэтому их трудно сравнивать таким образом.)