-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội
Đó là điều bắt buộc!
Observer design pattern có một vấn đề mình cần chia sẻ gấp đó là việc xử lý exception trong môi trường đa luồng. Đã có 2 lần mình mắc lỗi này, và lỗi này cực kì nghiêm trọng trên môi trường thật, nó làm treo cả một luồng nghiệp vụ luôn và phải mất rất nhiều công sức để tìm ra. Lần đầu tiên là vào năm 2015, mình đã quên bắt Exception trong lớp tính toán và khi exception xảy ra, hệ thống cứ đơ đơ như kiểu bị deadlock. Lần gần đây nhất là 2020 mình cũng hơi bất ngờ, do deploy thiếu file mà cái luồng xử lý nghiệp vụ nó bắn ra NoClassDefFoundError mà cái này thì nó không thừa kế từ Exception mà thừa kế từ Throwable (mình lại chỉ catch Exception), và thế là lại treo 1 lần nữa. 2 lần đã dạy cho mình rất nhiều bài học, để hôm nay mình có thể viết được bài này. Thật tiếc là 2 lần lỗi đều là những nghiệp vụ phức tạp, nên mình sẽ dùng bài toán đơn giản để minh họa lỗi và cách xử lý nhé.
Bài toán thực tế
Giả sử chúng ta có một chương trình chuyên thực hiện phép chia và phép chia này rất nặng và chúng ta dùng 1 thread riêng để xử lý. Code sẽ thế này:
public class ObserverDivider {
private Queue<DivideRequest> queue = new LinkedBlockingQueue<>();
private ObserverDivider() {
Thread newThread = new Thread(() -> {
while (true) {
DivideRequest request = queue.poll();
if(request != null) {
request.callback.accept(request.a / request.b);
}
}
});
newThread.start();
}
public void divide(Integer a, Integer b, Consumer<Integer> callback) {
queue.offer(new DivideRequest(a, b, callback));
}
public static void main(String[] args) throws Exception {
ObserverDivider divider = new ObserverDivider();
divider.divide(10, 5, result -> { // 1. Phép tính này được thự thi
System.out.println("10 / 5 = " + result);
});
Thread.sleep(50);
divider.divide(10, 0, result -> {
System.out.println("10 / 0 = " + result); // 2. chương trình sẽ bị treo từ đây
});
divider.divide(20, 5, result -> {
System.out.println("20 / 5 = " + result); // 3. Phép tính này sẽ không được thực thi
});
}
@AllArgsConstructor
public class DivideRequest {
private Integer a;
private Integer b;
private Consumer<Integer> callback;
}
Nhìn vào đây chúng ta sẽ mong muốn cả phép tính sẽ được thực thi đúng không? Nhưng không, vì 10/0 sẽ ném ra ArithmeticException
, vậy nên luồng xử lý sẽ bị dừng lại và sẽ không có bất cứ phép tính nào được thực hiện nữa. Output:
10 / 5 = 2
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
at com.example.stackoverflow.ObserverDivider.lambda$new$0(ObserverDivider.java:17)
at java.lang.Thread.run(Thread.java:748)
Những cách xử lý
Vậy có cách nào để xử lý Exception? Sẽ có 2 cách để chúng ta xử lý.
- Nếu nghiệp vụ của chúng ta yêu cầu nếu có lỗi xảy ra hãy bỏ qua, chúng ta có thể in ra log hoặc trả về kết quả mặc định, code sẽ thế này:
private ObserverDivider() {
Thread newThread = new Thread(() -> {
while (true) {
DivideRequest request = queue.poll();
if (request != null) {
try {
request.callback.accept(request.a / request.b);
}
catch (Throwable e) {
e.printStackTrace();
}
}
}
});
newThread.start();
}
- Nếu nghiệp vụ yêu cầu chúng ta phải xử lý lỗi xảy ra, chúng ta sẽ cần thay đổi lớp Callback và sử dụng thế này:
public class ObserverDivider {
private Queue<DivideRequest> queue = new LinkedBlockingQueue<>();
private ObserverDivider() {
Thread newThread = new Thread(() -> {
while (true) {
DivideRequest request = queue.poll();
if (request != null) {
try {
request.callback.onResult(request.a / request.b);
}
catch (Throwable e) {
request.callback.onError(e);
}
}
}
});
newThread.start();
}
public void divide(Integer a, Integer b, Callback callback) {
queue.offer(new DivideRequest(a, b, callback));
}
public static void main(String[] args) throws Exception {
ObserverDivider divider = new ObserverDivider();
divider.divide(10, 5, new Callback() {
@Override
public void onResult(Integer result) {
System.out.println("10 / 5 = " + result);
}
@Override
public void onError(Throwable e) {
System.out.println("10 / 5: " + e);
}
});
Thread.sleep(50);
divider.divide(10, 0, new Callback() {
@Override
public void onResult(Integer result) {
System.out.println("10 / 0 = " + result);
}
@Override
public void onError(Throwable e) {
System.out.println("10 / 0: " + e);
}
});
divider.divide(20, 5, new Callback() {
@Override
public void onResult(Integer result) {
System.out.println("20 / 5 = " + result);
}
@Override
public void onError(Throwable e) {
System.out.println("20 / 5: " + e);
}
});
}
public static interface Callback {
void onResult(Integer result);
void onError(Throwable e);
}
}
public class DivideRequest {
private Integer a;
private Integer b;
private Callback callback;
}
Output:
10 / 5 = 2
10 / 0: java.lang.ArithmeticException: / by zero
20 / 5 = 4
Tổng kết
Chúng ta có thể thấy lập trình Observer với async cũng không phải là đơn giản, nó làm cho source code của chúng ta dài ra rất nhiều, và nếu quên bắt Exception, rất có thể chúng ta sẽ gặp lỗi rất nghiệm trọng, vậy hãy luôn chú ý việc này nhé
-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội