Là một kỹ sư phụ trợ, chúng tôi phải đối mặt với các tình huống xử lý dữ liệu không đồng bộ. Hôm nay chúng ta hãy xem nó được thực hiện như thế nào trong java và nhiều cách khác nhau để làm điều đó. ThreadThành phần rất cơ bản nhưng rất mạnh mẽ của Java concurrency là Thread. Luồng của Java thực sự được liên kết với Luồng của hệ điều hành. Cách rất cơ bản để tạo Thread là bằng cách mở rộng nó và ghi đè lên run : Bắt đầu chuỗi gây ra run() được gọi là.
Java giải quyết những vấn đề này với giao diện Runnable. Trong thực tế, Thread có một phương thức được nạp chồng có Runnable. RunnableRunnable là một giao diện chỉ có một phương thức: run(). Có, Runnable là một giao diện chức năng và phiên bản của nó có thể được tạo bằng hàm lambda. Tuy nhiên, đó là một cách dễ dàng để làm điều này; đối với những thứ phức tạp, chúng tôi có thể muốn triển khai nó. Xem sự khác biệt ở đây. Đó là tất cả về yêu cầu: Mặc dù Runnable có một run(), nó không phải là một Luồng mà chỉ là một lớp Java cho đến khi nó được kiểm soát bởi (được chuyển tới) Luồng. Sự bắt đầu của chuỗi làm cho đối tượng có thể chạy được run() được gọi là. Đúng vậy, Java đã giải quyết được nó trong phiên bản 1.5 và nó có thể gọi là . Callable<V>Callable là một giao diện chung. Tại sao? Chạy lệnh này của giá trị trả về như lệnh chung chạy lệnh này. Callable là một giao diện quá chức năng và call() là phương thức duy nhất, một phương thức không đối số ném Exception và trả về giá trị lệnh này chạy chung. Việc triển khai Callable rất giống với Runnable: Xem tại đây, cuộc gọi xử lý dữ liệu và trả về một giá trị có thể được thu thập sau khi thực thi. Nhưng có một sự khác biệt lớn trong việc gọi nó? Chúng tôi sử dụng ExecutorService để gọi và Future để nắm giữ kết quả. Hãy nói về lý do tại sao. Như bạn có thể thấy, không có hành vi nào được kiểm soát khi tạo và chạy các Luồng (Runnable hoặc Callable quá). Chúng ta có thể muốn kiểm soát số lượng luồng đang chạy tại một thời điểm vì mỗi luồng được liên kết với các luồng của hệ điều hành. Số lượng Chủ đề chúng tôi chạy phải ít hơn số lõi CPU có sẵn. Tất cả cùng nhau, Java giải quyết nó bằng
cách ExecutorService giao diện. Các kiểu dữ liệu chuỗi :Kiểu String :String là một lớp đối tượng được Java dựng sẵn, dùng để khởi tạo và xử lý các chuỗi văn bản. Có 2 cách khởi tạo chuỗi: //cách 1 String name = "Hoang"; //cách 2 String name = new String("Hoang");
Một số phương thức phổ biến của String :
So sánh chuỗi :
Kiểu StringBuilder, StringBuffer :Cũng là các lớp đối tượng do Java dựng sẵn giúp xử lý chuỗi, nhưng khác với String ở chỗ: giá trị thuộc tính của đối tượng String ko bị thay đổi mỗi khi gọi phương thức của chính nó, còn giá trị của đối tượng StringBuilder hoặc StringBuffer bị thay đổi mỗi khi gọi phương thức. Cách khởi tạo: StringBuilder name = new StringBuilder("Hoang"); StringBuffer name = new StringBuffer("Hoang"); Sự khác nhau giữa StringBuilder và StringBuffer: cơ bản thì 2 kiểu dữ liệu giống nhau về các phương thức xử lý chuỗi, nhưng khác nhau về mục đích sử dụng. StringBuffer được sử dụng trong các bài toán liên quan đến đa luồng, đồng bộ dữ liệu. Còn trong các bài toán thông thường thì StringBuilder được dùng thường xuyên hơn. Các phương thức phổ biến của StringBuilder :
Một số kiểu dữ liệu mảng :Kiểu Array :Array là một đối tượng biểu diễn một tập hợp hữu hạn các phần tử liền nhau trong bộ nhớ và có chung kiểu dữ liệu. Mảng kiểu Array phải được xác định trước kích thước và các ô nhớ nối tiếp nhau trong vùng nhớ. Khai báo và khởi tạo: int mang1[] = new int[3]; double[] mang2 = new double[3]; String mang3[] = new String[] {"An", "Binh", "Hoa"}; int mang4[][] = new int[3][4]; Khi bạn viết “int mang[]”, bạn mới chỉ khai báo mảng, mảng chỉ thực sự được khởi tạo bởi từ khóa “new”. Dòng 1 và 2 là 2 cách viết ký hiệu mảng, bạn dùng cách nào cũng được. Khi chúng ta khởi tạo mảng, mặc định giá trị các phần tử đều bằng 0 hết với kiểu int, bằng 0.0 với kiểu double, bằng null với các kiểu dữ liệu có cấu trúc ví dụ như String. Dòng 3 là cách truyền luôn giá trị cho các phần tử, mảng sẽ tự động xác định kích thước. Dòng 4 là cách khởi tạo mảng 2 chiều. Cách duyệt mảng : Dùng for: for(int i=0; i<mang.length; i++) { System.out.println(mang[i]); } Dùng for…each: String mang[] = new String[] {"An", "Binh", "Hoa"}; for(String phanTu : mang) { System.out.println(phanTu); } Vòng for…each khác for ở chỗ:
Cách duyệt mảng 2 chiều : for(int i=0; i<mang.length; i++) { for(int j=0; j<mang[0].length; j++) { //bla bla } } Ý tưởng về cách biểu diễn mảng trong Java có khác với C. Trong C, mảng 2 chiều thực chất là mảng 1 chiều mà các hàng nối tiếp nhau, còn trong Java thì coi mọi mảng đều là mảng 1 chiều, mỗi phần tử là một mảng một chiều khác. Do đó “mang.length” trả về số hàng của mảng (lưu ý “length” ở đây là thuộc tính, không phải phương thức “length()” như chuỗi), còn “mang[0].length” trả về số cột của mảng. Một số phương thức xử lý mảng hữu hiệu trong thư viện Arrays :Gói thư viện java.util.Arrays chứa một số phương thức xử lý mảng, đem lại tiện ích cho người lập trình thay vì duyệt và xử lý mảng thủ công, ví dụ như:
public class HocSinh implements Comparable<HocSinh> { private double diem; @Override public int compareTo(HocSinh o) { double hieu = this.diem - o.diem; if(hieu > 0) { return 1; } else if(hieu < 0) { return -1; } else { return 0; } } } public class QuanLy { Comparator<HocSinh> sapXepDiemHSTangDan = new Comparator<HocSinh>() { public int compare(HocSinh o1, HocSinh o2) { double hieu = o1.diem - o2.diem; if(hieu > 0) { return 1; } else if(hieu < 0) { return -1; } else { return 0; } } } } Nếu dùng Comparator thì phương thức sort() phải truyền thêm tham số thứ 2 chính là tên Comparator mà bạn vừa định nghĩa. Arrays.sort(mang, sapXepDiemHSTangDan); Sự khác nhau giữa Comparable và Comparator:
Kiểu ArrayList :ArrayList là một lớp đối tượng được Java dựng sẵn, khắc phục mặt hạn chế của kiểu Array, đó là biểu diễn được một danh sách mà số lượng phần tử thay đổi được, có thể tuỳ ý thêm, sửa, xoá phần tử khỏi danh sách (lưu ý ArrayList chỉ biểu diễn mảng 1 chiều). Khai báo: ArrayList<HocSinh> hocSinh = new ArrayList<HocSinh>(); Các phương thức chính của ArrayList:
Lưu ý, vì danh sách kiểu ArrayList có khả năng thay đổi kích thước, nên khi bạn đem phương thức size() làm điều kiện thoát vòng lặp for, nó vẫn thay đổi giá trị mỗi lần gọi. Điều này dẫn đến tình trạng khi bạn thực hiện xoá phần tử, ví dụ bạn xoá phần tử thứ 5, phần tử tiếp theo sẽ thụt vào thế chỗ phần tử mất đi, do đó nếu biến i tiếp tục tăng lên 6, bạn sẽ bỏ lỡ mất 1 phần tử. Vì thế bạn cần phải thêm i– để tránh bị nhảy cóc. for(int i=0; i<danhSach.size(); i++) { if(danhSach.get(i)==num) { danhSach.remove(i); i--; } } ArrayList chỉ có thể lưu trữ dữ liệu kiểu đối tượng, nên nếu bạn muốn lưu số, bạn phải dùng lớp đối tượng của kiểu dữ liệu đó. Kiểu int có lớp Integer, kiểu double có lớp Double. ArrayList<Integer> listInt = new ArrayList<Integer>(); listInt.add(1); listInt.add(2); |