Nói rằng tôi có một AtomicReference
vào một danh sách các đối tượng:AtomicReference đến một đối tượng có thể thay đổi và tầm nhìn
AtomicReference<List<?>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>());
Chủ đề Một thêm yếu tố vào danh sách này: batch.get().add(o);
Sau đó, thread B mất danh sách và, ví dụ: lưu trữ nó trong một DB: insertBatch(batch.get());
Tôi có phải thực hiện đồng bộ hóa bổ sung khi viết (Thr hay không) ead A) và đọc (Thread B) để đảm bảo thread B thấy danh sách theo cách A còn lại, hoặc là điều này được chăm sóc bởi AtomicReference?
Nói cách khác: nếu tôi có AtomicReference đối với một đối tượng có thể thay đổi và một chuỗi thay đổi đối tượng đó, các chuỗi khác có thấy thay đổi này ngay lập tức không?
Edit:
Có lẽ một số mã ví dụ là theo thứ tự:
public void process(Reader in) throws IOException {
List<Future<AtomicReference<List<Object>>>> tasks = new ArrayList<Future<AtomicReference<List<Object>>>>();
ExecutorService exec = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; ++i) {
tasks.add(exec.submit(new Callable<AtomicReference<List<Object>>>() {
@Override public AtomicReference<List<Object>> call() throws IOException {
final AtomicReference<List<Object>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>(batchSize));
Processor.this.parser.parse(in, new Parser.Handler() {
@Override public void onNewObject(Object event) {
batch.get().add(event);
if (batch.get().size() >= batchSize) {
dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));
}
}
});
return batch;
}
}));
}
List<Object> remainingBatches = new ArrayList<Object>();
for (Future<AtomicReference<List<Object>>> task : tasks) {
try {
AtomicReference<List<Object>> remainingBatch = task.get();
remainingBatches.addAll(remainingBatch.get());
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException)cause;
}
throw (RuntimeException)cause;
}
}
// these haven't been flushed yet by the worker threads
if (!remainingBatches.isEmpty()) {
dao.insertBatch(remainingBatches);
}
}
gì xảy ra ở đây là tôi tạo ra bốn đề người lao động để phân tích một số văn bản (đây là Reader in
tham số cho phương thức process()
) . Mỗi công nhân lưu các dòng nó đã phân tích cú pháp trong một lô, và xóa sạch lô khi nó đầy (dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));
).
Vì số lượng dòng trong văn bản không phải là bội số của kích thước lô, các đối tượng cuối cùng sẽ kết thúc trong một đợt không bị xóa, vì nó không đầy. Các lô còn lại này do đó được chèn vào bởi luồng chính.
Tôi sử dụng AtomicReference.getAndSet()
để thay thế gói đầy đủ bằng một gói trống. Nó chương trình này chính xác liên quan đến luồng?
OK, tôi đã thêm một số mã ví dụ vào câu hỏi của mình ở trên. Tôi sử dụng 'AtomicReference.getAndSet()' để thay thế một lô đầy đủ bằng một gói trống mới. Tôi vẫn cần đồng bộ hóa bổ sung? –
Có, mã của bạn là chính xác, mặc dù việc sử dụng «AtomicReference' dường như không cần thiết ở đây. – Tudor
@Tudor đang nghĩ chính xác điều tương tự.Trong thực tế, getAndSet() có thể không làm những gì anh ta muốn vì nó sẽ nhận được giá trị hiện tại và sau đó thay đổi giá trị của AtomicReference. –