ExecutorService trong Java là gì và cách tạo nó?



Bài viết này trình bày khái niệm về giao diện con ExecutorService trong Java với nhiều ví dụ khác nhau để giải thích việc tạo và quản lý luồng trong Java.

Ngôn ngữ lập trình Java hoạt động rất hiệu quả với các ứng dụng yêu cầu các tác vụ phải được thực thi đồng thời trong một luồng. Khó ứng dụng nào có thể thực thi một số lượng lớn các luồng đồng thời. Vì vậy, để khắc phục vấn đề này, đi kèm với ExecutorService, là một giao diện con của . Trong bài viết này, chúng ta sẽ thảo luận về chức năng của ExecutorService trong Java. Sau đây là các chủ đề được đề cập trong blog này:

Executor Framework là gì?

Việc tạo và thực thi một hoặc hai luồng đồng thời khá dễ dàng hơn. Nhưng nó trở nên khó khăn khi số lượng đề tăng lên một con số đáng kể. Các ứng dụng đa luồng lớn sẽ có hàng trăm luồng chạy đồng thời. Do đó, hoàn toàn hợp lý khi tách việc tạo luồng khỏi quản lý luồng trong một ứng dụng.





Người thực hiện là một giúp bạn tạo và quản lý các luồng trong một ứng dụng. Các giúp bạn trong các nhiệm vụ sau.

  • Tạo luồng: Nó cung cấp nhiều phương pháp khác nhau để tạo luồng giúp chạy các ứng dụng của bạn đồng thời.



  • Quản lý luồng: Nó cũng quản lý vòng đời của luồng. Bạn không cần phải lo lắng nếu luồng đang hoạt động, bận hoặc chết trước khi gửi tác vụ để thực thi.

  • Task Submission And Execution: Khung thực thi cung cấp các phương thức để gửi tác vụ trong nhóm luồng, Nó cũng cung cấp quyền quyết định xem luồng sẽ được thực thi hay không.

thi hành viên dịch vụ-thi hành viên dịch vụ trong java -edureka

Ví dụ về ExecutorService trong Java

Nó là một giao diện con của khung thực thi bổ sung các chức năng nhất định để quản lý vòng đời luồng của một ứng dụng. Nó cũng cung cấp một phương thức submit () có thể chấp nhận cả runnable và callable các đối tượng.



Trong ví dụ sau, chúng ta sẽ tạo một ExecutorService với một luồng duy nhất và sau đó gửi tác vụ sẽ được thực thi bên trong luồng.

import java.util.concurrent.ExecutorService import java.util.concurrent.Executor public class Ví dụ {public static void main (String [] args) {System.out.println ('Inside:' + Thread.currentThread (). getName ( )) System.out.println ('tạo ExecutorService') ExecutorService thi hành viên chức năng = Executor.newSingleThreadExecutor () System.out.println ('tạo một runnable') Runnable runnable = () -> {System.out.println ('bên trong: '+ Thread.currentThread (). GetName ())} System.out.println (' đệ trình tác vụ được chỉ định bởi runnable đến thi hành dịch vụ ') thi hành công vụ.submit (runnable)}}
 Đầu ra: Inside: main tạo ExecutorService tạo một runnable gửi tác vụ được chỉ định bởi runnable tới dịch vụ thực thi bên trong: pool-1-thread-1

Trên chỉ ra cách chúng ta có thể tạo một ExecutorService và thực thi một tác vụ bên trong trình thực thi. Nếu một nhiệm vụ được gửi để thực thi và luồng hiện đang bận thực hiện một tác vụ khác, thì tác vụ đó sẽ đợi trong hàng đợi cho đến khi luồng rảnh để thực thi nó.

Khi bạn chạy chương trình trên, chương trình sẽ không bao giờ thoát. Bạn sẽ cần phải tắt nó một cách rõ ràng vì dịch vụ thực thi tiếp tục lắng nghe các tác vụ mới.

Triển khai Java ExecutorService

ExecutorService rất giống với một nhóm luồng. Trên thực tế, việc triển khai ExecutorService trong java.util.concurrent gói hàng là một triển khai threadpool. ExecutorService có các triển khai sau trong gói java.util.concurrent:

ThreadPoolExecutor

ThreadPoolExecutor thực thi các tác vụ đã cho bằng cách sử dụng một trong các luồng được tổng hợp nội bộ của nó.

Tạo một threadPoolExecutor

int corePoolSize = 5 int maxPoolSize = 10 long keepAliveTime = 5000 ExecutorService threadPoolExecutor = new threadPoolExecutor (corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, LinkedBlockingQueue mới ())

SchedisedThreadPoolExecutor

Java.util.concurrent.SchedisedThreadPoolExecutor là một ExecutorService có thể lên lịch các tác vụ để chạy sau một khoảng thời gian trì hoãn hoặc thực thi lặp đi lặp lại với một khoảng thời gian cố định giữa mỗi lần thực thi.

Thí dụ

ScheduredExecutorService đã lên lịch biểuexecutorervice = Executor.newSchedisedThreadPool (5) SchedisedFuture đã lên lịch trình = cycleExecutorService.schedule (new Callable () {public Object call () ném Exception {System.out.println ('thi hành') trả về 'được gọi là'}}, 5, TimeUnit. GIÂY)

ExecutorService Sử dụng

Có một số cách khác nhau để ủy quyền nhiệm vụ cho ExecutorService.

  • thực thi (Runnable)

  • đệ trình (Runnable)

  • invokeAny ()

  • invokeAll ()

Thực thi Runnable

Thực thi Java ExecutorService (Runnable) nhận một đối tượng java.lang.Runnable và thực thi nó một cách không đồng bộ.

ExecutorService executorService = Executor.newSingleThreadExecutor () thi hànhService.execute (new Runnable () {public void run () {System.out.println ('asynchronous task')}}) executeService.shutdown ()

Không có cách nào để lấy kết quả của Runnable thực thi, vì bạn phải sử dụng Callable.

Gửi Runnable

Phương thức Java ExecutorService submit (Runnable) nhận triển khai Runnable và trả về một đối tượng trong tương lai. Đối tượng tương lai có thể được sử dụng để kiểm tra xem Runnable đã thực thi xong chưa.

Future future = executeService.submit (new Runnable () {public void run () {System.out.println (: asynchronous task ')}}) future.get () // trả về null nếu nhiệm vụ được hoàn thành đúng cách.

Gửi có thể gọi

Phương thức Java ExecutorService submit (Callable) tương tự như submit (Runnable) nhưng nó sử dụng Java Callable thay vì Runnable.

Tương lai tương lai = executeService.submit (new Callable () {public Object call () ném Exception {System.out.println ('Asynchronous callable') return 'Callable Result'}}) System.out.println ('future.get ( ) = 'future.get ())
 Đầu ra: Tương lai có thể gọi không đồng bộ = Callable Result

invokeAny ()

Phương thức invokeAny () nhận một tập hợp các đối tượng có thể gọi được. Gọi phương thức này không trả về bất kỳ tương lai nào, nhưng trả về kết quả của một trong các đối tượng Có thể gọi.

ExecutorService executeService = Executor.newSingleThreadExecutor () Bộcallables = new HashSet() callables.add (new Callable () {public String call () ném Exception {return notask A '}}) callables.add (new Callable () {public String call () ném Exception {return notask B'} }) callables.add (new Callable () {public String call () throws Exception {return notask C '}}) String result = executiveService.invokeAny (callables) System.out.println (' result = '+ result) thi hành .tắt()

Khi bạn chạy đoạn mã trên, kết quả sẽ thay đổi. Nó có thể là Nhiệm vụ A, Nhiệm vụ B, v.v.

InvokeAll ()

Phương thức invokeAll () gọi tất cả các đối tượng có thể gọi được truyền dưới dạng tham số. Nó trả về các đối tượng trong tương lai có thể được sử dụng để lấy kết quả thực hiện của mỗi Callable.

ExecutorService executeService = Executor.newSingleThreadExecutor () Bộcallables = new HashSet() callables.add (new Callable () {public String call () ném Exception {return 'Task A'}}) callables.add (new Callable () {public String call () ném Exception {return 'Task B'} }) callables.add (new Callable () {public String call () ném Exception {return 'Task C'}}) Danh sáchfutures = executeService.invokeAll (có thể gọi) cho (Tương lai tương lai: tương lai) {System.out.println ('future.get =' + future.get ())} executeService.shutdown ()

Runnable và Callable

Các giao diện có thể chạy và có thể gọi được rất giống nhau. Sự khác biệt có thể nhìn thấy trong khai báo của các giao diện. Cả hai giao diện đại diện cho một tác vụ có thể được thực hiện đồng thời bởi một luồng hoặc ExecutorService.

Tuyên bố có thể gọi:

public interface Có thể gọi {public object call () throws Exception}

Khai báo Runnable:

giao diện chung Runnable {public void run ()}

Sự khác biệt chính giữa hai phương thức này là phương thức call () có thể trả về một đối tượng từ lời gọi phương thức. Và phương thức call () có thể ném một trong khi phương thức run () không thể.

sử dụng trình lặp trong java

hủy bỏ nhiệm vụ

Bạn có thể hủy nhiệm vụ đã gửi cho ExecutorService bằng cách chỉ cần gọi phương thức hủy trong tương lai được gửi khi nhiệm vụ được gửi.

future.cancel ()

ExecutorService Shutdown

Để giữ cho các luồng chạy ngay cả sau khi thực thi hoàn tất, bạn nên tắt ExecutorService.

tắt()

Để kết thúc các luồng bên trong ExecutorService, bạn có thể gọi phương thức shutdown ().

executeService.shutdown ()

Điều này đưa chúng ta đến phần cuối của bài viết này, nơi chúng ta đã học cách chúng ta có thể sử dụng ExecutorService để thực thi các tác vụ trong một luồng. Tôi hy vọng bạn rõ ràng với tất cả những gì đã được chia sẻ với bạn trong hướng dẫn này.

Nếu bạn thấy bài viết này về “ExecutorService trong Java” có liên quan, hãy xem một công ty học trực tuyến đáng tin cậy với mạng lưới hơn 250.000 người học hài lòng trải dài trên toàn cầu.

Chúng tôi ở đây để giúp bạn từng bước trong hành trình của mình và đưa ra chương trình giảng dạy được thiết kế cho sinh viên và các chuyên gia muốn trở thành Nhà phát triển Java. Khóa học được thiết kế để cung cấp cho bạn khởi đầu về lập trình Java và đào tạo bạn về cả khái niệm Java cốt lõi và nâng cao cùng với nhiều giống Ngủ đông & .

Nếu bạn gặp bất kỳ câu hỏi nào, vui lòng đặt tất cả các câu hỏi của bạn trong phần nhận xét của “ExecutorService trong Java” và nhóm của chúng tôi sẽ sẵn lòng trả lời.