Làm thế nào để bạn giết một chủ đề trong Java?


374

Làm thế nào để bạn giết một java.lang.Threadtrong Java?


2
cho đến bây giờ bạn không thể giết một chủ đề; bởi vì hủy () không bao giờ được thực hiện do dễ bị khóa chết
AZ_

1
Tôi thích câu trả lời liên quan đến ExecutorStatuscâu hỏi này: stackoverflow.com/questions/2275443/how-to-timeout-a-thread
Kirby

9
@loungerdork "Tôi nghĩ rằng Java nên thực hiện một phương thức dừng / hủy an toàn cho các luồng chạy mà bạn không kiểm soát được, mặc dù có những cảnh báo mất khóa và các cạm bẫy khác" Vì vậy, bạn muốn dừng luồng không an toàn . Tôi nghĩ bạn đã có một cái.
DJClayworth

4
Thật đáng ngạc nhiên khi loại câu hỏi nào sẽ nhận được 212 upvote trong năm 2009. Điều này sẽ bị hủy ngay lập tức ngày hôm nay.
Jonathon Reinhart

7
@JonathonReinhart: Tại sao vậy? Nó dường như là một câu hỏi chính đáng, ngay cả những ngày này. Có thể bạn không biết sự thất vọng mà nó gây ra khi bạn có các chuỗi chạy trốn và chỉ có thể sử dụng các hàm không dùng nữa để xử lý việc này bằng cách nào đó?
TFuto

Câu trả lời:


189

Xem chủ đềThread.stop() này của Sun về lý do tại sao họ không tán thành . Nó đi vào chi tiết về lý do tại sao đây là một phương pháp tồi và nên làm gì để ngăn chặn các luồng một cách an toàn nói chung.

Cách họ đề xuất là sử dụng một biến được chia sẻ làm cờ yêu cầu dừng luồng nền. Biến này sau đó có thể được đặt bởi một đối tượng khác yêu cầu kết thúc luồng.


1
nếu bạn kiểm tra luồng mà bạn đã ngắt isAlive () thì nó sẽ trả về cho bạn đúng và họ sẽ tiếp tục thêm vào Threadgroup hiện tại của bạn [], bạn có thể thấy điều này bằng cách sử dụng Thread.cienThread.getThreadgroup (). list (); nó sẽ in tất cả các luồng mà nó có và bạn sẽ thấy nhiều phiên bản của luồng nếu bạn lặp lại luồng của mình.
AZ_

3
Nếu bạn đang dùng PC thì không có vấn đề gì, nhưng nếu bạn đang phát triển một phần mềm cho thiết bị di động (android tôi đã trải nghiệm nó) thì bạn sẽ nhận được OutOfMemoryError
AZ_

2
Có thể / cần lưu ý rằng để đảm bảo liên lạc kịp thời về yêu cầu dừng qua cờ, biến phải biến động (hoặc quyền truy cập vào biến phải được đồng bộ hóa), như đã nêu trong khuyến nghị.
mtsz

2
Liên kết đó đã bị giết vào thời điểm này. Tôi đã có thể tìm thấy nó trên archive.org, mặc dù: web.archive.org/web/20090202093154/http://java.sun.com/j2se/ trộm
Jay Taylor

2
Tôi sử dụng phương pháp getConnection()từ java.sql.DriverManager. Nếu kết nối kết nối mất quá nhiều thời gian, tôi sẽ cố gắng giết luồng tương ứng bằng cách gọi Thread.interrupt()nhưng nó hoàn toàn không ảnh hưởng đến luồng. Các Thread.stop()tuy nhiên hoạt động, mặc dù oracle nói nó không nên làm việc nếu interrupt()không. Tôi tự hỏi làm thế nào để nó hoạt động và tránh sử dụng phương pháp không dùng nữa.
Daniel Lo

129

Nói chung là bạn không ..

Bạn yêu cầu nó làm gián đoạn bất cứ điều gì nó đang làm bằng cách sử dụng Thread.interrupt () (liên kết javadoc)

Một lời giải thích tốt về lý do tại sao trong javadoc ở đây (liên kết java technote)


@Fredrik Điều gì xảy ra với bối cảnh Thread khi interrupt()phương thức được gọi? Câu hỏi chính liên quan đến việc tạo nhật ký cho mỗi luồng mới.
ABcDexter

3
@ABcDexter Toàn bộ vấn đề là ngắt không làm gián đoạn bất cứ điều gì, nó chỉ báo hiệu cho mã trong luồng (hoặc mã được gọi bởi luồng) mà ai đó đã yêu cầu nó làm gián đoạn bất cứ điều gì nó đang làm. Sau đó, luồng được cho là sẽ dừng quá trình xử lý và trả về, giống như nếu nó được thực hiện đúng như những gì nó cần (và tại thời điểm đó, bối cảnh của luồng có lẽ cũng bị loại bỏ). OTOH, nếu bạn thực sự buộc dừng chủ đề, câu hỏi của bạn sẽ thực sự tốt và câu trả lời không xác định.
Fredrik

64

Trong các luồng Java không bị giết, nhưng việc dừng một luồng được thực hiện theo cách hợp tác . Các chủ đề được yêu cầu chấm dứt và sau đó chủ đề có thể tắt một cách duyên dáng.

Thông thường một volatile booleantrường được sử dụng mà luồng kiểm tra định kỳ và chấm dứt khi nó được đặt thành giá trị tương ứng.

Tôi sẽ không sử dụng một booleanđể kiểm tra xem các chủ đề nên chấm dứt . Nếu bạn sử dụng volatilenhư một công cụ sửa đổi trường, điều này sẽ hoạt động đáng tin cậy, nhưng nếu mã của bạn trở nên phức tạp hơn, thay vào đó sử dụng các phương thức chặn khác trong whilevòng lặp, điều đó có thể xảy ra, rằng mã của bạn sẽ không chấm dứt hoặc ít nhất là mất nhiều thời gian hơn khi bạn có thể muốn.

Một số phương pháp thư viện chặn nhất định hỗ trợ gián đoạn.

Mỗi luồng đã có trạng thái ngắt cờ boolean và bạn nên sử dụng nó. Nó có thể được thực hiện như thế này:

public void run() {
   try {
      while (!interrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }
}

public void cancel() { interrupt(); }

Mã nguồn được điều chỉnh từ Java đồng thời trong thực tiễn . Vì cancel()phương thức này là công khai, bạn có thể để một luồng khác gọi phương thức này như bạn muốn.


Và phải làm gì nếu bạn chạy mã không đáng tin cậy như một plugin hoặc tập lệnh? Java đã nhúng hộp cát cho mã không tin cậy. Và hộp cát đó là vô dụng, nó cho phép hoạt động mà không cần dừng mạnh mẽ. Hãy tưởng tượng bạn đang viết một trình duyệt trên java. Khả năng giết tập lệnh trang tùy ý là vô giá.
ayvango

@ayvango Sau đó, bạn phải chạy tập lệnh đó trong hộp cát của riêng bạn. Hộp cát Java bảo vệ máy khỏi ứng dụng, không phải các bộ phận của ứng dụng với nhau.
David Schwartz

@DavidSchwartz có nghĩa là tôi chỉ nên sử dụng nền tảng khác sau đó java?
ayvango

@ayvango Bạn vẫn có thể sử dụng hộp cát Java để bảo vệ máy khỏi ứng dụng của bạn. Nhưng nếu bạn muốn bảo vệ các phần của ứng dụng khỏi các phần khác trong ứng dụng của mình, bạn sẽ cần chọn một số công cụ có thể làm điều đó.
David Schwartz

@DavidSchwartz ASFAIK các công cụ như vậy không thể tồn tại nếu nó không được hỗ trợ ở cấp độ nền tảng. Nhưng tất nhiên nhiệm vụ có thể được giải quyết với công cụ kịch bản được giải thích đầy đủ. Nó có thể tính giảm như erlang làm và làm những thứ khác.
ayvango

20

Một cách là bằng cách đặt một biến lớp và sử dụng nó như một trọng điểm.

Class Outer {
    public static volatile flag = true;

    Outer() {
        new Test().start();
    }
    class Test extends Thread {

        public void run() {
            while (Outer.flag) {
                //do stuff here
            }
        }
    }

}

Đặt một biến lớp bên ngoài, tức là flag = true trong ví dụ trên. Đặt nó thành false để 'giết' chuỗi.


2
Cũng như một gợi ý phụ: Một biến như cờ chỉ hoạt động, khi luồng chạy và nó không bị kẹt. Thread.interrupt () sẽ giải phóng chuỗi ra khỏi hầu hết các điều kiện chờ đợi (chờ, ngủ, đọc mạng, v.v.). Do đó, bạn không bao giờ nên bắt InterruptedException để thực hiện công việc này.
ReneS

12
Điều này không đáng tin cậy; làm "cờ" volatileđể đảm bảo nó hoạt động tốt ở mọi nơi. Lớp bên trong không tĩnh, do đó, cờ nên là một biến thể hiện. Cờ phải được xóa trong một phương thức truy cập để có thể thực hiện các hoạt động khác (như ngắt). Tên "cờ" không được mô tả.
erickson

2
Tôi không nhận được điều "trong khi" trong phương thức chạy. Điều này không có nghĩa là bất cứ điều gì được viết trong phương thức chạy sẽ được lặp lại? đây không phải là thứ chúng tôi muốn chủ đề thực hiện ở vị trí đầu tiên :(

2
+1 đang làm trong khi (! Thread.cienThread (). IsInteruppted ()) được ưa thích
Toby

2
Cả hai trường hợp đều thất bại, ví dụ như khi bạn mở một quy trình bên ngoài trong khi {// open ext process} và quá trình đó bị treo, bây giờ chủ đề sẽ không bị gián đoạn cũng không đến cuối để kiểm tra điều kiện Boolean của bạn, và bạn bị treo trái ... hãy thử với ví dụ: khởi chạy giao diện điều khiển python bằng java.exec và thử lấy lại quyền điều khiển mà không cần thoát lối ra, và xem có cách nào để giết quá trình đó và thoát ra .... không có cách nào để thoát khỏi tình huống như vậy ...
Space Rocker

11

Có một cách bạn có thể làm điều đó. Nhưng nếu bạn phải sử dụng nó, hoặc bạn là một lập trình viên tồi hoặc bạn đang sử dụng một mã được viết bởi các lập trình viên xấu. Vì vậy, bạn nên suy nghĩ về việc ngừng trở thành một lập trình viên tồi hoặc ngừng sử dụng mã xấu này. Giải pháp này chỉ dành cho các tình huống khi KHÔNG CÓ CÁCH KHÁC.

Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );

2
Không có lý do nào để làm điều này, bởi vì vẫn có thể gọi cho công chúng Thread.stopngay cả khi nó không được chấp nhận.
Lii

1
@Lii Thread.stoplàm tương tự nhưng cũng kiểm tra quyền truy cập và quyền. Sử dụng Thread.stoplà khá rõ ràng và tôi không nhớ lý do tại sao tôi sử dụng Thread.stop0thay vì đó. Có lẽ Thread.stopkhông hoạt động cho trường hợp đặc biệt của tôi (Weblogic trên Java 6). Hoặc có thể vì Thread.stopbị phản đối và gây ra cảnh báo.
VadimPlatonov 7/10/2015

1
Trong kịch bản của tôi, đây là cách duy nhất để ngăn chặn một chuỗi chạy bất tận. Vì một số lý do .stop () đã không dừng chuỗi, nhưng stop0 () đã làm
fiffy

10

Tôi muốn thêm một số quan sát, dựa trên các ý kiến ​​đã tích lũy.

  1. Thread.stop() sẽ dừng một luồng nếu trình quản lý bảo mật cho phép.
  2. Thread.stop()là nguy hiểm. Phải nói rằng, nếu bạn đang làm việc trong môi trường JEE và bạn không kiểm soát được mã được gọi, điều đó có thể là cần thiết; xem Tại sao Thread.stop không dùng nữa?
  3. Bạn không bao giờ nên dừng lại một chủ đề công nhân container. Nếu bạn muốn chạy mã có xu hướng bị treo, (cẩn thận) bắt đầu một chuỗi daemon mới và theo dõi nó, giết nếu cần thiết.
  4. stop()tạo ra một ThreadDeathErrorlỗi mới trên luồng gọi và sau đó ném lỗi đó vào luồng đích . Do đó, dấu vết ngăn xếp nói chung là vô giá trị.
  5. Trong JRE 6, stop()kiểm tra với người quản lý bảo mật và sau đó gọi các cuộc gọi stop1()đó stop0(). stop0()là mã gốc.
  6. Kể từ Java 13 Thread.stop()chưa bị xóa (nhưng), nhưng Thread.stop(Throwable)đã bị xóa trong Java 11. ( danh sách gửi thư , JDK-8204243 )

8

Tôi sẽ bình chọn cho Thread.stop() .

Ví dụ, bạn có một hoạt động lâu dài (như yêu cầu mạng). Giả sử bạn đang chờ phản hồi, nhưng nó có thể mất thời gian và người dùng điều hướng đến giao diện người dùng khác. Chủ đề chờ đợi này bây giờ là một) vô dụng b) vấn đề tiềm ẩn bởi vì khi anh ta nhận được kết quả, nó hoàn toàn vô dụng và anh ta sẽ kích hoạt các cuộc gọi lại có thể dẫn đến một số lỗi.

Tất cả điều đó và anh ta có thể xử lý phản hồi có thể là CPU mạnh. Và bạn, với tư cách là một nhà phát triển, thậm chí không thể ngăn chặn nó, bởi vì bạn không thể némif (Thread.currentThread().isInterrupted()) các dòng trong tất cả các mã.

Vì vậy, không có khả năng mạnh mẽ để ngăn chặn một chủ đề nó kỳ lạ.


Nếu hoạt động mạng đã được hủy bỏ một cách an toàn, chỉ cần ngắt chuỗi. Nếu hoạt động mạng không bị hủy bỏ an toàn, Thread.stop()dù sao bạn cũng không thể gọi an toàn. Bạn không bỏ phiếu cho Thread.stop(), bạn đang yêu cầu mọi người thực hiện mọi thao tác có thể mất nhiều thời gian để hủy bỏ an toàn. Và đó cũng có thể là một ý tưởng tốt, nhưng nó không liên quan gì đến việc thực hiện Thread.stop()như là cách để yêu cầu phá thai an toàn. Chúng tôi đã có interruptcho điều đó.
David Schwartz

"Vì vậy, việc không thể ngăn chặn một chủ đề thật kỳ lạ." - ... cho đến khi bạn nhìn sâu (như các nhà thiết kế Java đã làm) và kết luận rằng không có giải pháp khả thi về mặt kỹ thuật nào không tệ hơn là phản đối stop.
Stephen C

5

Câu hỏi khá mơ hồ. Nếu bạn có ý nghĩa là làm thế nào để tôi viết một chương trình để một luồng ngừng chạy khi tôi muốn nó đến thì các phản hồi khác sẽ hữu ích. Nhưng nếu bạn có nghĩa là tôi có một trường hợp khẩn cấp với một máy chủ thì tôi không thể khởi động lại ngay bây giờ và tôi chỉ cần một luồng cụ thể để chết, hãy đến những gì có thể, sau đó bạn cần một công cụ can thiệp để khớp với các công cụ giám sát như thế nào jstack.

Với mục đích này, tôi đã tạo ra jkillthread . Xem hướng dẫn sử dụng.


Cảm ơn bạn! Chính xác những gì tôi đang tìm kiếm!
Denis Kokorin

4

Tất nhiên có trường hợp bạn đang chạy một số loại mã không hoàn toàn đáng tin cậy. (Cá nhân tôi có điều này bằng cách cho phép các tập lệnh được tải lên thực thi trong môi trường Java của tôi. Vâng, có tiếng chuông báo động bảo mật vang lên ở mọi nơi, nhưng đó là một phần của ứng dụng.) Trong trường hợp không may này, trước hết bạn chỉ hy vọng bằng cách hỏi người viết kịch bản để tôn trọng một số loại tín hiệu chạy / không chạy boolean. An toàn thất bại duy nhất của bạn là gọi phương thức dừng trên luồng nếu, giả sử, nó chạy lâu hơn thời gian chờ.

Nhưng, đây chỉ là "đàng hoàng", và không tuyệt đối, bởi vì mã có thể bắt lỗi ThreadDeath (hoặc bất kỳ ngoại lệ nào bạn ném rõ ràng), và không nghĩ lại như một chủ đề lịch sự cần phải làm. Vì vậy, điểm mấu chốt là AFAIA không có sự thất bại tuyệt đối an toàn.


AFAIK ngày càng có nhiều dịch vụ trở nên hỗn hợp và sử dụng môi trường được quản lý để thực thi mã bên thứ 3 (plugin, tập lệnh, v.v.) mà họ không kiểm soát hoàn toàn mã, có vẻ như không hợp lý khi hoàn toàn lấy thread.stop khỏi bảng, vì đối với các kỹ sư dịch vụ, trạng thái phục vụ trực tiếp có thể tốt hơn vô hạn so với trạng thái không phục vụ (do bị treo (lấy đi các luồng) hoặc vòng lặp vô hạn bận rộn (lấy đi lõi))
Weipeng L

3

Không có cách nào để duyên dáng giết chết một chủ đề.

Bạn có thể cố gắng làm gián đoạn chuỗi, một chiến lược chung là sử dụng một viên thuốc độc để nhắn tin cho chuỗi để tự dừng lại

public class CancelSupport {
    public static class CommandExecutor implements Runnable {
            private BlockingQueue<String> queue;
            public static final String POISON_PILL  = stopnow”;
            public CommandExecutor(BlockingQueue<String> queue) {
                    this.queue=queue;
            }
            @Override
            public void run() {
                    boolean stop=false;
                    while(!stop) {
                            try {
                                    String command=queue.take();
                                    if(POISON_PILL.equals(command)) {
                                            stop=true;
                                    } else {
                                            // do command
                                            System.out.println(command);
                                    }
                            } catch (InterruptedException e) {
                                    stop=true;
                            }
                    }
                    System.out.println(“Stopping execution”);
            }

    }

}

BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);

http://anandsekar.github.io/celon-support-for-threads/


2

Nói chung, bạn không giết, dừng hoặc ngắt một chuỗi (hoặc kiểm tra xem nó bị gián đoạn ()), nhưng hãy để nó chấm dứt một cách tự nhiên.

Nó đơn giản. Bạn có thể sử dụng bất kỳ vòng lặp nào cùng với biến boolean (dễ bay hơi) bên trong phương thức run () để kiểm soát hoạt động của luồng. Bạn cũng có thể quay lại từ luồng hoạt động đến luồng chính để dừng nó.

Bằng cách này, bạn duyên dáng giết một chủ đề :).


1

Nỗ lực chấm dứt chủ đề đột ngột là thực tiễn lập trình xấu nổi tiếng và bằng chứng về thiết kế ứng dụng kém. Tất cả các luồng trong ứng dụng đa luồng đều chia sẻ một cách rõ ràng và ngầm chia sẻ cùng một trạng thái quy trình và buộc phải hợp tác với nhau để giữ cho nó nhất quán, nếu không ứng dụng của bạn sẽ dễ bị lỗi rất khó chẩn đoán. Vì vậy, trách nhiệm của nhà phát triển là đảm bảo sự nhất quán như vậy thông qua thiết kế ứng dụng cẩn thận và rõ ràng.

Có hai giải pháp đúng cho việc chấm dứt chủ đề được kiểm soát:

  • Sử dụng cờ biến động được chia sẻ
  • Sử dụng cặp phương thức Thread.interrupt () và Thread.interrupted ().

Có thể tìm thấy giải thích tốt và chi tiết về các vấn đề liên quan đến việc chấm dứt các luồng đột ngột cũng như các ví dụ về các giải pháp sai và đúng cho việc chấm dứt các luồng được kiểm soát tại đây:

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads


Vì các chương trình không còn được viết bởi nhà phát triển duy nhất, nên việc giết các chủ đề thường là cần thiết. Do đó không thể được coi là lập trình xấu. Tôi không thể tưởng tượng Linux mà không giết. Không có khả năng để giết chủ đề là khiếm khuyết Java.
Pavel Niedoba

1
Tuyệt vời, thưa ông ... Điều gì sẽ xảy ra nếu bạn phải gọi một thư viện bên thứ 3 nào đó mà bạn không có quyền kiểm soát và thời gian chờ bị lỗi và có thể bị treo một lần sau mỗi 1000-2000 lần khi được thực thi? Thực hành lập trình xấu hả? Vâng, bạn không thể luôn có quyền truy cập vào mã bạn đang sử dụng. Dù sao, op đang hỏi làm thế nào để giết một luồng không làm thế nào để kiểm soát dòng chảy của nó khi thiết kế mã của riêng mình ...
Arturas M

Câu hỏi đặt ra là điều gì sẽ xảy ra khi bạn giết một luồng có mutex sở hữu hoặc có một số khối bộ nhớ được phân bổ hoặc sẽ tạo ra một số sự kiện hoặc dữ liệu mà luồng khác đang chờ? Điều gì sẽ xảy ra với phần còn lại của logic ứng dụng của bạn? Bạn sẽ luôn có nguy cơ rằng vấn đề nhỏ và hiển nhiên sẽ được chuyển thành vấn đề phức tạp, khó có thể tái tạo và điều tra. Giết luồng là không an toàn vì nó có thể khiến ứng dụng của bạn ở một số trạng thái không nhất quán khác nhau. Hãy xem thông tin từ liên kết trên cert.org.
ZarathustrA

Chúng tôi có một luồng kiểm soát mà trên các điều kiện nhất định có thể quyết định rằng toàn bộ tính toán trở nên vô nghĩa. Nhiều runnables khác nhau làm công việc thực tế cần phải được tung tóe với một số biến thể của isInterrupted () tại bất kỳ nơi nào thuận tiện - thật kinh khủng! Sẽ tốt hơn rất nhiều nếu bộ điều khiển làm cho ThreadDeath nổi lên dường như không có chỗ đứng, làm sạch hoàn toàn tất cả các khối được đồng bộ hóa & cuối cùng. Mọi người đều nói rằng điều này rất dễ xảy ra lỗi, nhưng đối với các Chủ đề khá không liên quan, tôi không hiểu tại sao.
Daniel


1

Tôi đã không làm gián đoạn hoạt động trong Android, vì vậy tôi đã sử dụng phương pháp này, hoạt động hoàn hảo:

boolean shouldCheckUpdates = true;

private void startupCheckForUpdatesEveryFewSeconds() {
    Thread t = new Thread(new CheckUpdates());
    t.start();
}

private class CheckUpdates implements Runnable{
    public void run() {
        while (shouldCheckUpdates){
            //Thread sleep 3 seconds
            System.out.println("Do your thing here");
        }
    }
}

 public void stop(){
        shouldCheckUpdates = false;
 }

2
từ khóa dễ bay hơi nên được thêm vào ShouldCheckUpdates, bao gồm trình biên dịch tối ưu hóa với lưu trữ cục bộ của luồng.
Clinicux

1

'Giết một chủ đề' không phải là cụm từ phù hợp để sử dụng. Đây là một cách chúng ta có thể thực hiện hoàn thành / thoát duyên dáng của chuỗi theo ý muốn:

Runnable mà tôi đã sử dụng:

class TaskThread implements Runnable {

    boolean shouldStop;

    public TaskThread(boolean shouldStop) {
        this.shouldStop = shouldStop;
    }

    @Override
    public void run() {

        System.out.println("Thread has started");

        while (!shouldStop) {
            // do something
        }

        System.out.println("Thread has ended");

    }

    public void stop() {
        shouldStop = true;
    }

}

Lớp kích hoạt:

public class ThreadStop {

    public static void main(String[] args) {

        System.out.println("Start");

        // Start the thread
        TaskThread task = new TaskThread(false);
        Thread t = new Thread(task);
        t.start();

        // Stop the thread
        task.stop();

        System.out.println("End");

    }

}

từ khóa dễ bay hơi nên được thêm vào biến ShouldStop, trong trường hợp trình biên dịch tối ưu hóa với lưu trữ cục bộ của luồng.
Oleksii Kyslytsyn

0

Thread.stop không được dùng nữa, làm thế nào để chúng ta dừng một chủ đề trong java?

Luôn sử dụng phương thức ngắt và tương lai để yêu cầu hủy

  1. Khi tác vụ phản hồi tín hiệu ngắt, ví dụ, chặn phương thức lấy hàng đợi.
Callable < String > callable = new Callable < String > () {
    @Override
    public String call() throws Exception {
        String result = "";
        try {
            //assume below take method is blocked as no work is produced.
            result = queue.take();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return result;
    }
};
Future future = executor.submit(callable);
try {
    String result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    logger.error("Thread timedout!");
    return "";
} finally {
    //this will call interrupt on queue which will abort the operation.
    //if it completes before time out, it has no side effects
    future.cancel(true);
}
  1. Khi tác vụ không phản hồi tín hiệu ngắt. Giả sử tác vụ thực hiện I / O ổ cắm không phản hồi tín hiệu ngắt và do đó sử dụng phương pháp trên sẽ không hủy bỏ tác vụ, tương lai sẽ hết thời gian nhưng việc hủy trong khối cuối cùng sẽ không có hiệu lực , chủ đề sẽ tiếp tục nghe ổ cắm. Chúng ta có thể đóng ổ cắm hoặc gọi phương thức đóng trên kết nối nếu được thực hiện bởi pool.
public interface CustomCallable < T > extends Callable < T > {
    void cancel();
    RunnableFuture < T > newTask();
}

public class CustomExecutorPool extends ThreadPoolExecutor {
    protected < T > RunnableFuture < T > newTaskFor(Callable < T > callable) {
        if (callable instanceof CancellableTask)
            return ((CancellableTask < T > ) callable).newTask();
        else
            return super.newTaskFor(callable);
    }
}

public abstract class UnblockingIOTask < T > implements CustomCallable < T > {
    public synchronized void cancel() {
        try {
            obj.close();
        } catch (IOException e) {
            logger.error("io exception", e);
        }
    }

    public RunnableFuture < T > newTask() {
        return new FutureTask < T > (this) {
            public boolean cancel(boolean mayInterruptIfRunning) {
                try {
                    this.cancel();
                } finally {
                    return super.cancel(mayInterruptIfRunning);
                }
            }

        };
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.