Tôi có trường hợp sử dụng đến từ một vấn đề GUI mà tôi muốn gửi cho sự sagacity của bạn.Mẫu đơn không đồng bộ thông minh trong Java
Sử dụng trường hợp
Tôi có một giao diện hiển thị kết quả tính toán phụ thuộc vào một số thông số người dùng thiết lập trong một GUI. Ví dụ: khi người dùng di chuyển một thanh trượt, một số sự kiện được kích hoạt, tất cả sẽ kích hoạt tính toán mới. Khi người dùng điều chỉnh giá trị thanh trượt từ A đến B, hàng chục sự kiện sẽ được kích hoạt.
Nhưng tính toán có thể mất đến vài giây, trong khi điều chỉnh thanh trượt có thể kích hoạt sự kiện cứ sau 100 ms.
Làm thế nào để viết một chủ đề thích hợp mà có thể lắng nghe những sự kiện này, và loại lọc chúng để các repaint của kết quả là sống động? Lý tưởng nhất là bạn muốn một cái gì đó như
- bắt đầu một tính toán mới ngay khi nhận được sự kiện thay đổi đầu tiên;
- hủy tính toán đầu tiên nếu một sự kiện mới được nhận và bắt đầu một sự kiện mới với các thông số mới;
- nhưng đảm bảo rằng sự kiện cuối cùng sẽ không bị mất, vì tính toán hoàn thành cuối cùng cần phải là sự kiện có thông số được cập nhật lần cuối.
Những gì tôi đã cố gắng
Một người bạn của tôi (A. Cardona) đề xuất phương pháp này ở mức độ thấp của một chủ đề Updater có thể ngăn chặn quá nhiều sự kiện để kích hoạt một tính toán. Tôi sao chép-dán nó ở đây (GPL):
Ông đặt này trong một lớp học kéo dài Ðề tài:
public void doUpdate() {
if (isInterrupted())
return;
synchronized (this) {
request++;
notify();
}
}
public void quit() {
interrupt();
synchronized (this) {
notify();
}
}
public void run() {
while (!isInterrupted()) {
try {
final long r;
synchronized (this) {
r = request;
}
// Call refreshable update from this thread
if (r > 0)
refresh(); // Will trigger re-computation
synchronized (this) {
if (r == request) {
request = 0; // reset
wait();
}
// else loop through to update again
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void refresh() {
// Execute computation and paint it
...
}
Mỗi lần một sự kiện được gửi bởi GUI nói rằng thông số đã được thay đổi, chúng ta gọi là updater.doUpdate()
. Điều này gây ra phương pháp refresh()
được gọi là ít hơn nhiều. Nhưng tôi không kiểm soát được điều này.
Một cách khác?
Tôi đã tự hỏi nếu có một cách khác để làm điều đó, điều đó sẽ sử dụng các lớp jaca.concurrent. Nhưng tôi không thể phân loại trong khung công tác Executors thì tôi nên bắt đầu với cái gì.
Có ai trong số các bạn có kinh nghiệm với một ca sử dụng tương tự không?
Cảm ơn
giải pháp tốt. nhưng nó không rõ ràng với tôi cho dù có một cơ hội nhỏ mà sau khi 'worker1.cancel()', 'worker1.done()' vẫn được thực hiện, và nó có thể được thực hiện sau 'worker2.done()', tức là một kết quả cũ sẽ ghi đè lên một kết quả mới hơn. cần điều tra thêm một chút ở đây. – ZhongYu
Điều này không giải quyết được vấn đề làm thế nào để lô các yêu cầu, để tránh tình huống mà bạn đang hủy bỏ và khởi động lại các chủ đề nhiều lần trong một thời gian ngắn. –
Tôi không nghĩ rằng bạn có thể tránh việc hủy bỏ các yêu cầu, bởi vì bạn không bao giờ biết nếu một số yêu cầu là cuối cùng. Chắc chắn, bạn có thể chờ một chút trước khi sa thải nhân viên, để xem liệu có nhiều yêu cầu hơn không, nhưng điều đó sẽ chỉ làm cho bản cập nhật chậm hơn. –