Nếu bạn luôn gửi bản thực thi đến một nhóm luồng sau khi chọn() trả về, bạn có thể muốn hủy khóa ngay lập tức, vì bạn mất quyền kiểm soát thời gian Runnable sẽ thực hiện.
Ví dụ: Nếu bạn thực hiện lựa chọn tiếp theo() trước khi hủy khóa trước (chuỗi vẫn đang chờ thực thi), nó sẽ hợp lệ, khiến một luồng khác mang khóa đã được gửi đi. Nếu một trong các chủ đề này hủy khóa, người khác sẽ nhận được CancelledKeyException ngoài việc giới thiệu hành vi không mong muốn.
Ngay cả khi bạn hủy khóa, chủ đề có thể đăng ký cùng một kênh (cập nhật các phím chọn) trước khi kênh trở thành chưa đăng ký (do trước đó key.cancel()
). Điều gì, một lần nữa, sẽ gây ra một CancelledKeyException.
Để thoát khỏi cái bẫy này, bạn có thể muốn để xử lý các sự kiện luôn trong vòng lặp tiếp theo:
while (true) { // true or something less risky
//for each pendingTasks call
pool.execute(task);
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
key.cancel();
//store dispatch for the next while iteration
pendingTasks.add(task); // do not execute tasks before next select()
}
selector.select(TIMEOUT); // or selectNow if there are
//any pending events to handle.
}
thực hiện firt sẽ, gần như, không bao giờ quay trở lại chìa khóa, nhưng chọn() ở phần cuối của bạn loop MAY đảm bảo rằng kênh đã hủy không được đăng ký (chịu sự cố của bạn) từ bộ chọn.
Tuy nhiên, nếu bạn chỉ thực hiện nhiệm vụ trong cùng một chuỗi bạn nghe các sự kiện chọn của bạn, hãy cập nhật âm thanh dễ dàng và an toàn hơn.
bạn sẽ thay đổi thời gian chờ của bộ chọn nếu có các tác vụ vẫn đang chạy trên nhóm chủ đề của bạn.Nếu bạn sử dụng một thời gian chờ lớn trong lựa chọn của bạn() bạn có thể gây ra các chủ đề bị chặn cho việc đăng ký kênh mới/hiện tại để chọn. – paulosuzart