Làm thế nào để gọi một phương thức với một luồng riêng trong Java?


126

Hãy nói rằng tôi có một phương pháp doWork(). Làm thế nào để tôi gọi nó từ một chủ đề riêng biệt (không phải chủ đề chính).


Có một số ví dụ về câu hỏi liên quan gần đây này: giết một vòng lặp vô hạn trong java
Greg Hewgill

stackoverflow.com/questions/36832094/ Từ Tôi có một vấn đề tương tự, xin hãy giúp tôi giải quyết vấn đề này
Sruthi Acg

Bạn cũng có thể xem blog Reactive Java.danlew.net/2014/09/15/grokking-rxjava-part-1 cho các nhiệm vụ không đồng bộ
Nathan Dunn

Câu trả lời:


138

Tạo một lớp thực hiện Runnablegiao diện. Đặt mã bạn muốn chạy trong run()phương thức - đó là phương pháp mà bạn phải viết để tuân thủ Runnablegiao diện. Trong luồng "chính" của bạn, tạo một Threadlớp mới , truyền cho hàm tạo một thể hiện của bạn Runnable, sau đó gọi start()nó. startyêu cầu JVM thực hiện phép thuật để tạo một luồng mới và sau đó gọi runphương thức của bạn trong luồng mới đó.

public class MyRunnable implements Runnable {

    private int var;

    public MyRunnable(int var) {
        this.var = var;
    }

    public void run() {
        // code in the other thread, can reference "var" variable
    }
}

public class MainThreadClass {
    public static void main(String args[]) {
        MyRunnable myRunnable = new MyRunnable(10);
        Thread t = new Thread(myRunnable)
        t.start();
    }    
}

Hãy xem hướng dẫn đồng thời của Java để bắt đầu.

Nếu phương thức của bạn sẽ được gọi thường xuyên, thì có thể không đáng để tạo một luồng mới mỗi lần, vì đây là một hoạt động tốn kém. Có lẽ tốt nhất là sử dụng một nhóm chủ đề nào đó. Hãy nhìn vào Future, Callable, Executorlớp trong java.util.concurrentgói.


1
Điều gì nếu có một biến bạn muốn vượt qua?
Louis Rhys

8
Các run()phương pháp có không có thông số, vì vậy bạn không thể vượt qua một biến đó. Tôi khuyên bạn nên chuyển nó trong hàm tạo - Tôi sẽ chỉnh sửa câu trả lời của tôi để hiển thị điều đó.
Noel M

1
Có một cách ngắn để gọi 1 phương thức trong một luồng khác nhau? Tôi biết new Thread() { public void run() {myMethod();}}.start();đường đi, đó có phải là ngắn nhất?
Steven Roose

@NoelM bạn có thể giải thích sự khác biệt giữa câu trả lời của bạn và MANN không?
Asif Mushtaq

2
Câu trả lời của MANN sử dụng một triển khai ẩn danh của Runnable- của tôi là một lớp mở rộng Runnable. Và bởi vì tôi đã thực hiện rằng tôi có hàm tạo riêng của mình chuyển trạng thái vào đối tượng được khởi tạo.
Noel M

182
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // code goes here.
    }
});  
t1.start();

hoặc là

new Thread(new Runnable() {
     @Override
     public void run() {
          // code goes here.
     }
}).start();

hoặc là

new Thread(() -> {
    // code goes here.
}).start();

hoặc là

Executors.newSingleThreadExecutor().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

hoặc là

Executors.newCachedThreadPool().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

Điều này làm việc hoàn hảo cho những gì tôi đang làm. Cần thiết để chạy một dịch vụ web và cập nhật đồng thời một thanh tiến trình bằng cách sử dụng mẫu quan sát viên.
dpi

@Ashish: Hãy giải thích những gì và tại sao đã được chỉnh sửa?
MANN

1
@AshishAggarwal: Có vẻ kỳ lạ với tôi khi ai đó làm điều đó mà không xin phép tác giả!
MANN

@MANN bạn có thể giải thích lý do tại sao bạn sử dụng phương thức chạy trong tham số Thread không? hiệu suất nào tốt hơn?
Asif Mushtaq

1
Chúng ta có cần phải chấm dứt rõ ràng chủ đề? Không có nguy cơ tạo rò rỉ bộ nhớ bằng cách không chấm dứt rõ ràng luồng? Hoặc chủ đề chấm dứt khi nó được thực hiện với run()?
theyuv

59

Trong Java 8, bạn có thể làm điều này với một dòng mã.

Nếu phương thức của bạn không lấy bất kỳ tham số nào, bạn có thể sử dụng tham chiếu phương thức:

new Thread(MyClass::doWork).start();

Mặt khác, bạn có thể gọi phương thức trong biểu thức lambda:

new Thread(() -> doWork(someParam)).start();

xin lỗi để mang lại điều này nhưng chính xác nó ->có nghĩa là gì?
Kyle

1
Đó là cú pháp được sử dụng để tạo biểu thức lambda. Hãy xem các liên kết này để biết thêm thông tin: '->' làm gì trong Java? Hướng dẫn Java ™ - Biểu thức Lambda
Aaron Cohn

@AaronCohn người đàn ông thứ tuyệt vời! Bạn có biết bất kỳ sự thay thế nào cho các luồng trong Java không? Tôi đến từ thế giới Python, chúng tôi sẽ sử dụng Celery task queuecho những thứ không đồng bộ
Cgill

Java có mức độ trừu tượng cao hơn để xử lý Chủ đề , nhưng có lẽ bạn đang tìm kiếm thứ gì đó giống Akka hơn ?
Aaron Cohn

8

Một tùy chọn nhanh hơn khác để gọi mọi thứ (như DialogBoxes và MessageBoxes và tạo các luồng riêng biệt cho các phương thức an toàn không theo luồng) sẽ là sử dụng Biểu thức Lamba

  new Thread(() -> {
                      "code here"
            }).start();

3

Trước đây, tôi đã viết một lớp tiện ích đơn giản sử dụng dịch vụ thực thi JDK5 và thực thi các quy trình cụ thể trong nền. Do doWork () thường có giá trị trả về void, nên bạn có thể muốn sử dụng lớp tiện ích này để thực thi nó trong nền.

Xem bài viết này , nơi tôi đã ghi lại tiện ích này.


6
Tương lai và Callable làm điều này cho bạn.
Amir Afghani

Đúng họ làm. ý tưởng ở đây là trừu tượng hóa giao diện đằng sau một trình bao bọc không đồng bộ.
raja kolluru

Liên kết bị hỏng (404).
palacsint

3

Để đạt được điều này với RxJava 2.x, bạn có thể sử dụng:

Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();

Các subscribeOn()quy định cụ thể phương pháp mà lên lịch để chạy các hành động trên - RxJava có một số schedulers được xác định trước, bao gồm Schedulers.io()trong đó có một hồ bơi thread dành cho I / O hoạt động, và Schedulers.computation()đó là dành cho CPU hoạt động chuyên sâu.


3

Nếu bạn đang sử dụng ít nhất Java 8, bạn có thể sử dụng phương thức runAsynctừ lớp CompleteableFuture

CompletableFuture.runAsync(() -> {...});

Nếu bạn cần trả lại kết quả sử dụng supplyAsyncthay thế

CompletableFuture.supplyAsync(() -> 1);
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.