JavaRush /Blog Java /Random-VI /Đánh giá cao thời gian với các luồng
Andrei
Mức độ

Đánh giá cao thời gian với các luồng

Xuất bản trong nhóm

Lời nói đầu. Chú Petya

Vì vậy, giả sử chúng ta muốn đổ đầy một chai nước. Có sẵn chai và vòi nước của chú Petya. Hôm nay chú Petya đã lắp một chiếc vòi mới và chú không ngừng khen ngợi vẻ đẹp của nó. Trước đó, anh chỉ sử dụng vòi cũ, bị tắc nên dây chuyền đóng chai rất lớn. Sau khi mò mẫm một lúc, phía bên chỗ đổ nước vang lên tiếng rót nước, 2 phút sau chai vẫn đang trong giai đoạn rót, hàng người xếp hàng như thường lệ đã tụ tập phía sau chúng tôi, và hình ảnh trong đầu tôi là hình ảnh Bác quan tâm đến mức nào. Petya chỉ chọn những phân tử H2O tốt nhất vào chai của chúng tôi. Chú Petya, được cuộc đời huấn luyện, sẽ xoa dịu những kẻ đặc biệt hung hãn và hứa sẽ hoàn thành nhanh nhất có thể. Dùng xong chai, anh ta lấy chai tiếp theo và bật áp suất thông thường, điều này không bộc lộ hết khả năng của vòi mới. Người ta không vui... Trân trọng thời gian cùng suối - 1

Lý thuyết

Đa luồng là khả năng của một nền tảng để tạo ra nhiều luồng trong một tiến trình. Việc tạo và thực thi một luồng đơn giản hơn nhiều so với việc tạo một tiến trình, vì vậy nếu cần thực hiện một số hành động song song trong một chương trình thì các luồng bổ sung sẽ được sử dụng. Trong JVM, mọi chương trình đều chạy trong luồng chính và phần còn lại được khởi chạy từ nó. Trong cùng một tiến trình, các luồng có thể trao đổi dữ liệu với nhau. Khi bắt đầu một luồng mới, bạn có thể khai báo nó là một luồng người dùng bằng phương thức
setDaemon(true);
các luồng như vậy sẽ tự động chấm dứt nếu không còn luồng nào đang chạy khác. Các luồng có mức độ ưu tiên công việc (việc lựa chọn mức độ ưu tiên không đảm bảo rằng luồng có mức độ ưu tiên cao nhất sẽ hoàn thành nhanh hơn luồng có mức độ ưu tiên thấp hơn).
  • MIN_PRIORITY
  • NORM_PRIORITY (mặc định)
  • MAX_PRIORITY
Các phương thức cơ bản khi làm việc với luồng:
  • run()– thực thi luồng
  • start()– bắt đầu một chủ đề
  • getName()– trả về tên chủ đề
  • setName()– chỉ định tên của luồng
  • wait()– phương thức kế thừa, thread chờ phương thức được gọi notify()từ thread khác
  • notify()– phương thức được kế thừa, tiếp tục một luồng đã dừng trước đó
  • notifyAll()– phương thức được kế thừa, tiếp tục các luồng đã dừng trước đó
  • sleep()– tạm dừng luồng trong một thời gian nhất định
  • join()– chờ thread hoàn thành
  • interrupt()– làm gián đoạn quá trình thực thi luồng
Bạn có thể tìm thêm các phương pháp khác tại đây. Đã đến lúc nghĩ về các chủ đề mới nếu chương trình của bạn có:
  • Truy cập mạng
  • Truy cập hệ thống tập tin
  • GUI

Lớp chủ đề

Các luồng trong Java được biểu diễn dưới dạng một lớp Threadvà các lớp con của nó. Ví dụ dưới đây là cách triển khai đơn giản của lớp luồng.
import static java.lang.System.out;

public class ExampleThread extends Thread{

    public static void main(String[] args) {
        out.println("Основной поток");
        new ExampleThread().start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Kết quả là chúng tôi nhận được
Основной поток
Новый поток
Ở đây, chúng ta tạo lớp của mình và biến nó thành hậu duệ của lớp Thread, sau đó chúng ta viết phương thức main() để khởi chạy luồng chính và ghi đè phương thức run()lớp Thread. Bây giờ, sau khi tạo một thể hiện của lớp chúng ta và thực thi phương thức kế thừa của nó, start()chúng ta sẽ khởi chạy một luồng mới trong đó mọi thứ được mô tả trong phần nội dung của phương thức sẽ được thực thi run(). Nghe có vẻ phức tạp nhưng nhìn vào mã ví dụ thì mọi thứ sẽ rõ ràng.

Giao diện có thể chạy được

Oracle cũng đề xuất triển khai giao diện để bắt đầu một luồng mới Runnable, điều này mang lại cho chúng ta sự linh hoạt trong thiết kế hơn so với sự kế thừa duy nhất có sẵn trong ví dụ trước (nếu nhìn vào nguồn của lớp, Threadbạn có thể thấy rằng nó cũng triển khai giao diện Runnable). Hãy sử dụng phương pháp được đề xuất để tạo một chủ đề mới.
import static java.lang.System.out;

public class ExampleRunnable implements Runnable {

    public static void main(String[] args) {
        out.println("Основной поток");
        new Thread(new ExampleRunnable()).start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Kết quả là chúng tôi nhận được
Основной поток
Новый поток
Các ví dụ rất giống nhau, bởi vì Khi viết mã, chúng tôi phải triển khai một phương thức trừu tượng run()được mô tả trong giao diện Runnable. Việc khởi chạy một chủ đề mới có một chút khác biệt. Chúng tôi đã tạo một phiên bản của lớp Threadbằng cách chuyển một tham chiếu đến một phiên bản triển khai giao diện của chúng tôi dưới dạng tham số Runnable. Cách tiếp cận này cho phép bạn tạo các luồng mới mà không cần kế thừa trực tiếp lớp Thread.

Hoạt động lâu dài

Ví dụ sau sẽ cho thấy rõ lợi ích của việc sử dụng nhiều thread. Giả sử chúng ta có một nhiệm vụ đơn giản đòi hỏi một số phép tính dài dòng, trước bài viết này, chúng ta đã giải quyết nó theo một phương pháp, có thể main()chia nó thành các phương pháp riêng biệt để dễ nhận thức, thậm chí có thể là các lớp, nhưng bản chất sẽ giống nhau. Tất cả các hoạt động sẽ được thực hiện tuần tự lần lượt. Hãy mô phỏng các phép tính nặng và đo thời gian thực hiện chúng.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 1");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 2");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}
Kết quả là chúng tôi nhận được
complete 1
complete 2
complete 3
программа выполнялась 9885 миллисекунд
Thời gian thực hiện còn nhiều điều mong muốn, và suốt thời gian này chúng ta đang nhìn vào một màn hình đầu ra trống, và tình huống rất giống với câu chuyện về chú Petya, chỉ có điều bây giờ trong vai trò của chú ấy, chúng tôi, những nhà phát triển, chưa tận dụng được tất cả các khả năng của các thiết bị hiện đại. Chúng tôi sẽ cải thiện.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        new MyThread(1).start();
        new MyThread(2).start();
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}

class MyThread extends Thread{
int n;

MyThread(int n){
    this.n = n;
}

    @Override
    public void run() {
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete " + n);
    }
}
Kết quả là chúng tôi nhận được
complete 1
complete 2
complete 3
программа выполнялась 3466 миллисекунд
Thời gian chạy đã giảm đáng kể (hiệu ứng này có thể không đạt được hoặc thậm chí có thể tăng thời gian thực thi trên các bộ xử lý không hỗ trợ đa luồng). Điều đáng chú ý là các luồng có thể kết thúc không theo thứ tự và nếu nhà phát triển cần khả năng dự đoán các hành động, anh ta phải triển khai nó một cách độc lập cho một trường hợp cụ thể.

Nhóm chủ đề

Các luồng trong Java có thể được kết hợp thành các nhóm; lớp này được sử dụng cho việc này ThreadGroup. Các nhóm có thể bao gồm cả các chủ đề đơn lẻ và toàn bộ nhóm. Điều này có thể thuận tiện nếu bạn cần làm gián đoạn các luồng liên quan, chẳng hạn như với mạng khi mất kết nối. Bạn có thể đọc thêm về các nhóm tại đây. Tôi hy vọng bây giờ chủ đề đã trở nên rõ ràng hơn với bạn và người dùng của bạn sẽ hài lòng.
Trân trọng thời gian cùng suối - 2
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION