Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 36 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
36
Dung lượng
3,69 MB
Nội dung
Phát triển với Java thời gian thực, Phần 1: Khai thác các đặc tính độc nhất của Java thời gian thực Tận dụng hiệu năng Java thời gian thực trong ứng dụng của bạn Sean C. Foley, Phát triển phần mềm, IBM Tóm tắt: Bộ Java thời gian thực (Real-time Java™) kết hợp dễ dàng việc lập trình bằng ngôn ngữ Java theo hiệu năng do ứng dụng yêu cầu mà phải phù hợp với các ràng buộc thời gian thực. Các phần mở rộng của ngôn ngữ Java đưa ra các đặc tính về môi trường thời gian thực mà đang thiếu trong môi trường thời gian chạy Java truyền thống. Bài này, bài đầu tiên trong loạt bài ba phần, mô tả một số đặc tính này và giải thích cách bạn có thể áp dụng chúng để đạt được hiệu năng thời gian thực trong các ứng dụng của chính mình. Java thời gian thực là một bộ các tăng cường cho ngôn ngữ Java, cung cấp cho các ứng dụng một mức hiệu năng thời gian thực, vượt trội hiệu năng của công nghệ Java chuẩn. Hiệu năng thời gian thực khác với hiệu năng thông lượng truyền thống, là một thước đo điển hình của tổng số các chỉ thị, tác vụ, hoặc công việc có thể được thực hiện trong khoảng thời gian ấn định. Hiệu năng thời gian thực tập trung vào thời gian mà một ứng dụng yêu cầu để đáp ứng các kích thích bên ngoài mà không vượt quá các ràng buộc thời gian cho trước. Trong trường hợp của các hệ thống thời gian thực cứng (hard real-time), các ràng buộc như vậy không bao giờ được vượt quá; các hệ thống thời gian thực mềm (soft real-time) có một dung sai cao hơn đối với các vi phạm. Hiệu năng thời gian thực đòi hỏi chính ứng dụng phải giành được quyền điều khiển của bộ xử lý sao cho nó có thể trả lời các kích thích, và trong khi trả lời các tác nhân kích thích đó thì bộ mã của ứng dụng không bị khóa do thực hiện các quy trình tương tranh trong máy ảo đó. Java thời gian thực đưa ra độ đáp ứng mà trước đây chưa được thoả mãn trong các ứng dụng Java. Một máy ảo Java (JVM) thời gian thực có thể tận dụng các dịch vụ hệ điều hành thời gian thực (RTOS) để cung cấp các khả năng thời gian thực cứng, hoặc nó có thể chạy trên nhiều hệ điều hành thông thường đối với các áp dụng có các ràng buộc thời gian thực mềm dẻo hơn. Một số công nghệ sử dụng trong Java thời gian thực trở nên “miễn phí” khi bạn chuyển sang sử dụng máy ảo Java thời gian thực. Nhưng để khai thác một số đặc tính của Java thời gian thực, cần phải có một số thay đổi về ứng dụng. Các đặc tính này là trọng tâm của bài viết này. Các quy trình con phải bị ràng buộc Một JVM phục vụ một ứng dụng cho trước bằng cách thực hiện công việc mà ứng dụng đó chỉ điều khiển theo cách lỏng. Một vài quy trình thời gian chạy con làm việc trong JVM, gồm: Gom rác: Đây là công việc để phục hồi lại các khối nhớ thời gian chạy (run-time memory) mà ứng dụng đã loại bỏ. Việc gom rác có thể làm chậm việc thực thi ứng dụng trong một khoảng thời gian. Nạp lớp: Quy trình này — gọi như vậy vì các ứng dụng Java được nạp ở mức chi tiết của các lớp, liên quan đến việc nạp các cấu trúc ứng dụng — các chỉ thị, và các tài nguyên khác từ hệ thống tệp hoặc mạng. Trong Java chuẩn, ứng dụng nạp từng lớp khi nó được tham chiếu lần đầu (nạp chậm). Biên dịch động đúng thời (JIT dynamic compilation): Nhiều máy ảo sử dụng việc biên dịch động của các phương thức từ ngôn ngữ máy của Java (Java bytecode) sang các chỉ thị máy riêng khi ứng dụng đang chạy. Mặc dù việc này cải thiện được hiệu năng, hoạt động biên dịch tự nó có thể gây ra sự trì hoãn tạm thời, khóa việc chạy mã ứng dụng. Lập lịch: Trong Java chuẩn, cho phép mức điều khiển tối thiểu để ứng dụng ra lệnh cả việc lập lịch việc chạy các xử lí (threads) của chính mình lẫn lập lịch của ứng dụng tương quan với các ứng dụng khác đang chạy trên cùng hệ điều hành. Tất cả các quy trình con này có thể gây trở ngại đến khả năng phản hồi các tác nhân kích thích bên ngoài của một ứng dụng, vì chúng có thể làm chậm việc thực thi bộ mã ứng dụng. Thí dụ một chuỗi chỉ thị hẳn có thể được lên lịch thực hiện để trả lời một tín hiệu từ mạng, hệ thống radar, bàn phím, hoặc bất kỳ thiết bị nào khác. Một ứng dụng thời gian thực có một khoảng thời gian tối thiểu chấp nhận được trong đó một quy trình không liên quan đến, chẳng hạn như cho phép gom rác làm chậm việc thực hiện chuỗi chỉ thị trả lời. Java thời gian thực đưa ra các công nghệ đa dạng được thiết kế để giảm can thiệp đến ứng dụng khỏi các quy trình con ẩn này. Các công nghệ “miễn phí” này xuất hiện khi bạn chuyển sang JVM thời gian thực bao gồm việc gom rác đặc biệt có hạn chế khoảng thời gian và tác động của các gián đoạn đối với việc thu gom, tải lớp đặc biệt mà cho phép hiệu năng được tối ưu hoá vào lúc khởi động, thay vì việc tối ưu hoá bị chậm, khoá và đồng bộ hoá đặc biệt, và lập lịch xử lí ưu tiên đặc biệt với việc tránh bị đảo ngược quyền ưu tiên. Tuy nhiên, đòi hỏi một số thay đổi cho ứng dụng — cụ thể là khai thác các đặc tính do Đặc tả Thời gian Thực cho Java (RTSJ) đưa ra. RTSJ đảm bảo một API có nhiều đặc tính thời gian thực trong các JVM. Một số các đặc tính này có tính bắt buộc khi thực hiện đặc tả, số khác thì tuỳ ý. Đặc tả bao hàm các lĩnh vực chung về: Lập lịch thời gian thực Quản lý nhớ nâng cao Các bộ định thời gian phân giải cao Xử lý sự kiện không đồng bộ Ngắt không đồng bộ các xử lí Các xử lí thời gian thực RTSJ định nghĩa javax.realtime.RealtimeThread — là một lớp con của lớp chuẩn java.lang.Thread. Trên chính nó, RealtimeThread tạo ra một số đặc tính tiên tiến của đặc tả. Thí dụ các xử lí thời gian thực là chủ thể của bộ lập lịch xử lí thời gian thực. Bộ lập lịch đảm bảo một phạm vi duy nhất các quyền ưu tiên lập lịch và có thể thực hiện chính sách lập lịch thời gian thực vào trước - ra trước (đảm bảo các xử lí có quyền ưu tiên cao nhất được thực hiện không bị gián đoạn), cùng với việc kế thừa quyền ưu tiên (một thuật toán tránh các xử lí quyền ưu tiên thấp hơn giữ vô hạn một khoá mà một xử lí có quyền ưu tiên cao hơn đang yêu cầu và được chạy không bị cản trở — tình huống này được xem như đảo quyền ưu tiên). Bạn có thể xây dựng nên một cách rõ ràng các cá thể của RealtimeThread (xử lí thời gian thực) trong mã của bạn. Nhưng cũng có thể thay đổi ứng dụng của bạn theo một cách tối thiểu để xử lí thời gian thực, nên tránh được sự cố gắng phát triển đáng kể và các chi phí liên quan. Thể hiện sau đây là các ví dụ khác nhau về các cách để cho phép tạo xử lí thời gian thực ít can thiệp nhất và minh bạch nhất. (Bạn có thể tải về mã nguồn cho toàn bộ các thí dụ trong bài viết.) Các kỹ thuật này cho phép một ứng dụng khai thác các xử lí thời gian thực với sự cố gắng tối thiểu và cho phép ứng dụng giữ được sự tương thích với các máy ảo chuẩn. Chỉ định kiểu xử lí theo quyền ưu tiên Liệt kê 1 trình bày một khối mã gán một xử lí thời gian thực hoặc xử lí thông thường với giá trị ưu tiên. Nếu nó đang chạy trên một máy ảo thời gian thực, một số xử lí có thể là xử lí thời gian thực. Liệt kê 1. Gán lớp xử lí theo quyền ưu tiên import javax.realtime.PriorityScheduler; import javax.realtime.RealtimeThread; import javax.realtime.Scheduler; public class ThreadLogic implements Runnable { static void startThread(int priority) { Thread thread = ThreadAssigner.assignThread( priority, new ThreadLogic()); thread.start(); } public void run() { System.out.println("Running " + Thread.currentThread()); } } class ThreadAssigner { static Thread assignThread(int priority, Runnable runnable) { Thread thread = null; if(priority <= Thread.MAX_PRIORITY) { thread = new Thread(runnable); } else { try { thread = RTThreadAssigner.assignRTThread(priority, runnable); } catch(LinkageError e) {} if(thread == null) { priority = Thread.MAX_PRIORITY; thread = new Thread(runnable); } } thread.setPriority(priority); return thread; } } class RTThreadAssigner { static Thread assignRTThread(int priority, Runnable runnable) { Scheduler defScheduler = Scheduler.getDefaultScheduler(); PriorityScheduler scheduler = (PriorityScheduler) defScheduler; if(priority >= scheduler.getMinPriority()) { return new RealtimeThread( null, null, null, null, null, runnable); } return null; } } Mã trong Liệt kê 1 phải được biên dịch bằng các lớp RTSJ. Vào thời gian chạy, nếu không tìm thấy các lớp thời gian thực, mã sẽ nắm bắt được LinkageError bị máy ảo loại bỏ và tạo các đối tượng xử lí Java thông thường thay cho các xử lí thời gian thực. Việc này cho phép mã chạy trên bất kỳ máy ảo nào, dù có thời gian thực hay không. Trong Liệt kê 1, phương thức cung cấp các đối tượng RealtimeThread được tách riêng thành một lớp của chính nó. Với cách này, phương thức không được xác thực cho đến khi lớp được nạp vào, điều được làm khi phương thức assignRTThread được truy cập đầu tiên. Khi lớp được nạp, bộ kiểm tra ngôn ngữ máy của máy ảo thời gian thực cố gắng kiểm tra lại lớp RealtimeThread có phải là một lớp con của lớp Thread, hay không nó thông báo thất bại với một lỗi NoClassDefFoundError nếu không tìm ra các lớp thời gian thực. Chỉ định các xử lí nhờ phản chiếu Liệt kê 2 trình bày một kỹ thuật thay thế có cùng hiệu quả như Liệt kê 1. Nó khởi động bằng một giá trị ưu tiên để xác định kiểu xử lí mong muốn, tạo ra hoặc là một xử lí thời gian thực hoặc một xử lí thông thường dựa trên lớp tên. Mã phản chiếu trông chờ vào sự tồn tại của một hàm kiến thiết trong lớp mà lấy một cá thể của java.lang.Runnable làm đối số cuối cùng và chuyển giá trị rỗng cho tất cả đối số khác. Liệt kê 2. Sử dụng phản chiếu để chỉ định các xử lí import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ThreadLogic implements Runnable { static void startThread(int priority) { Thread thread = ThreadAssigner.assignThread( priority, new ThreadLogic()); thread.start(); } public void run() { System.out.println("Running " + Thread.currentThread()); } } class ThreadAssigner { static Thread assignThread(int priority, Runnable runnable) { Thread thread = null; try { thread = assignThread(priority <= Thread.MAX_PRIORITY, runnable); } catch(InvocationTargetException e) { } catch(IllegalAccessException e) { } catch(InstantiationException e) { } catch(ClassNotFoundException e) { } if(thread == null) { thread = new Thread(runnable); priority = Math.min(priority, Thread.MAX_PRIORITY); } thread.setPriority(priority); return thread; } static Thread assignThread(boolean regular, Runnable runnable) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException { Thread thread = assignThread( regular ? "java.lang.Thread" : "javax.realtime.RealtimeThread", runnable); return thread; } static Thread assignThread(String className, Runnable runnable) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException { Class clazz = Class.forName(className); Constructor selectedConstructor = null; Constructor constructors[] = clazz.getConstructors(); top: for(Constructor constructor : constructors) { Class parameterTypes[] = constructor.getParameterTypes(); int parameterTypesLength = parameterTypes.length; if(parameterTypesLength == 0) { continue; } Class lastParameter = parameterTypes[parameterTypesLength - 1]; if(lastParameter.equals(Runnable.class)) { for(Class parameter : parameterTypes) { if(parameter.isPrimitive()) { continue top; } } if(selectedConstructor == null || selectedConstructor.getParameterTypes().length > parameterTypesLength) { selectedConstructor = constructor; } } } if(selectedConstructor == null) { throw new InstantiationException( "no compatible constructor"); } Class parameterTypes[] = selectedConstructor.getParameterTypes(); int parameterTypesLength = parameterTypes.length; Object arguments[] = new Object[parameterTypesLength]; arguments[parameterTypesLength - 1] = runnable; return (Thread) selectedConstructor.newInstance(arguments); } } [...]... hoà nhập các phần tử của Java thời gian thực vào ứng dụng Java của bạn Nó bao hàm một số đặc điểm lập lịch và quản lý bộ nhớ mà bạn hẳn muốn sử dụng để thực hiện hiệu năng thời gian thực Đây là một điểm xuất phát để bạn tận dụng các lợi ích truyền thống của ngôn ngữ Java, chẳng hạn như sự tương tác và an toàn, và kết hợp chúng với các đặc tính mới cho phép bạn thoả mãn các ràng buộc thời gian thực mà... dụng của bạn đòi hỏi Trong phần tiếp theo ở loạt bài này, bạn sẽ tìm hiểu các kỹ thuật để chuyển một ứng dụng hiện hành sang Java thời gian thực Bài cuối sẽ xây dựng trên hai phần đầu và dẫn bạn qua việc thiết kế, xác thực, và gỡ lỗi một hệ thống thời gian thực mà hợp nhất với Java thời gian thực Mục lục Các quy trình con phải bị ràng buộc Các xử lí thời gian thực Các vùng nhớ tách biệt Các. .. bạn đang cân nhắc sử dụng các tuỳ chọn lập lịch và vùng nhớ Việc lập trình đối với các môi trường thời gian thực nói chung là một nhiệm vụ thách thức hơn lập trình các ứng dụng truyền thống đơn giản, và Java thời gian thực đưa ra các thách thức của chính nó Bảng 2 liệt kê một số phức tạp mà có thể nảy sinh khi sử dụng vùng nhớ bổ sung, các NHRT, và các đặc tính thời gian thực khác: Bảng 2 Một số phức... phép nó chạy hiệu quả nhất Dự định của RTSJ là cho phép các nhà phát triển viết ra các ứng dụng chạy trong các ràng buộc thời gian thực được yêu cầu Chỉ cần sử dụng bộ lập lịch và các xử lí thời gian thực là có thể đủ thực hiện được mục tiêu đó Nếu không, sự phát triển hiện đại hơn có thể là cần thiết để tận dụng một hoặc nhiều đặc tính hiện đại hơn do máy ảo thực hiện Kết luận Phần 1 Bài viết này đã... 2 không cần biên dịch với các lớp thời gian thực trên classpath (một biến môi trường để JVM và Java tìm ra các thư viện lớp), do các xử lí thời gian thực được tạo ra bằng cách sử dụng phản chiếu Java Chỉ định kiểu xử lí bằng sự kế thừa lớp Ví dụ tiếp theo minh họa cách có thể xử lí thời gian thực của việc thay đổi sự kế thừa của một lớp cho trước Bạn có thể tạo ra hai phiên bản của một lớp xử lí cho... máy ảo thời gian thực (và có đầy đủ khả năng trong các máy ảo khác) Ứng dụng có thể bao gồm các xử lí quản lí-sự kiện của mức ưu tiên cao, thu thập dữ liệu từ các đầu vào bên ngoài và lưu lại dữ liệu để xử lý Do tính nhất thời và không đồng bộ của chúng, các xử lí quản lí-sự kiện này có lẽ thích hợp đối với việc quản lý bộ nhớ xen kẽ, và chúng có lẽ phụ thuộc nặng nhất vào các ràng buộc thời gian thực. .. thước và số lượng các vùng Nếu các vùng đang được sử dụng, bạn phải cẩn thận khi thiết kế sắp xếp thứ tự của các ngăn xếp vùng của các xử lí, và phải duy trì nhận thức về các qui tắc gán Các tuỳ chọn để lập lịch mã nhạy thời gian Khi bạn sử dụng các vùng nhớ heap khác, bạn có thể chọn dùng javax.realtime.NoHeapRealtimeThread (NHRT - xử lí thời gian thực không có đống), một lớp con của javax.realtime.RealtimeThread,... được gói trong một cài đặt của java. lang.Runnable, thì một số tuỳ chọn là có thể để gửi đi bộ mã đó Bạn có thể chọn xây dựng nên một xử lí để khai thác bộ mã, hoặc sử dụng các bộ xử lý sự kiện không đồng bộ mà tận dụng các vùng đệm của các xử lí để thực hiện bộ mã theo yêu cầu, hoặc sử dụng các kết hợp của hai cái trên Bảng 1 trình bày một phân tích tổng quát về các đặc tính của các lựa chọn khả dĩ khác... tệp lớp ThreadContainer vừa được biên dịch này trong ứng dụng của bạn chứ không phải tệp cũ khi chạy nó bằng một JVM thời gian thực Các vùng nhớ tách biệt Phổ biến cho tất cả các JVM, gồm cả các JVM thời gian thực, là đống rác được thu gom (garbage-collected heap) JVM phục hồi lại bộ nhớ từ đống qua việc gom rác Các JVM thời gian thực có các thuật toán thu gom rác được thiết kế riêng để tránh hoặc giảm... được thực hiện một phần bởi sự áp đặt của các qui tắc gán Các nguyên tắc này ra lệnh rằng các đối tượng được phân bổ từ các vùng nhớ chưa được khoanh vùng không thể trỏ đến các đối tượng được khoanh vùng Điều này đảm bảo rằng khi các đối tượng được khoanh vùng được giải phóng, các đối tượng từ các vùng nhớ khác không bị bỏ lại với các tham chiếu đến các đối tượng không tồn tại Hình 1 minh hoạ các vùng . Phát triển với Java thời gian thực, Phần 1: Khai thác các đặc tính độc nhất của Java thời gian thực Tận dụng hiệu năng Java thời gian thực trong ứng dụng của bạn Sean C. Foley, Phát triển. với các ràng buộc thời gian thực. Các phần mở rộng của ngôn ngữ Java đưa ra các đặc tính về môi trường thời gian thực mà đang thiếu trong môi trường thời gian chạy Java truyền thống. Bài này,. thời gian thực. Nhưng để khai thác một số đặc tính của Java thời gian thực, cần phải có một số thay đổi về ứng dụng. Các đặc tính này là trọng tâm của bài viết này. Các quy trình con phải bị