Khi nào bạn gọi thread.run () của java thay vì thread.start ()?


109

Khi nào bạn sẽ gọi Java's thread.run()thay vì thread.start()?


47
Khi tôi là phương thức thread.start ()? :)
Bill the Lizard

3
@blank, Câu trả lời đơn giản là: t.run()khi bạn muốn chạy ttác vụ của chuỗi hiện tại và t.start()khi bạn muốn chạy ttác vụ của tchính chuỗi đó. Hoặc bạn đang yêu cầu các trường hợp sử dụng thực tế?
Pacerier

2
Khi bạn là một tên ngốc và muốn dành một giờ để gỡ lỗi mã đa luồng chỉ để nhận ra sau đó rằng bạn nên gọi start()! Giống như tôi ... Phương pháp này không nên công khai!
Pierre Henry

Câu trả lời:


113

Bạn có thể muốn gọi run () trong một thử nghiệm đơn vị cụ thể liên quan chặt chẽ đến chức năng chứ không phải với đồng thời.


95

Không bao giờ. Việc gọi run () trực tiếp chỉ thực thi mã một cách đồng bộ (trong cùng một luồng), giống như một cuộc gọi phương thức bình thường.


25
"Không bao giờ" là một chút quá tuyệt đối. Có thể không phải lúc nào bạn cũng muốn một luồng mới và vẫn thực thi mã?
Tomalak

4
Có thể, nhưng trong trường hợp đó sẽ rất lãng phí nếu tạo một Thread mới chỉ để gọi phương thức run (). Tốt hơn nên tạo một Runnable impl và chạy trong luồng hoặc cấu trúc đó và bắt đầu một Thread mới với nó.
Scott Bale

1
Chỉ cần xem lại ... nếu không bao giờ, tại sao phương thức được công khai?
trống

4
Nó công khai vì Thread triển khai Runnable. Bạn có thể phân lớp Thread và ghi đè run (), có tác dụng tương tự như đặt mã của bạn trong Runnable và chuyển nó vào phương thức khởi tạo Thread. Tuy nhiên, thực hành tốt hơn là sử dụng một đối tượng Runnable riêng biệt, vì điều đó giúp bạn linh hoạt hơn (chẳng hạn như chuyển nó cho Người thực thi, v.v.).
Adam Crume

2
Hãy để tôi đưa ra một ví dụ cụ thể mà tôi hiện đang làm việc: Tôi có một chương trình có thể chạy dưới dạng GUI hoặc từ dòng lệnh. Trong trường hợp GUI, tôi muốn đối tượng thực hiện công việc nặng nhọc chạy trên một chuỗi riêng và gửi các bản cập nhật đến gui. Trong chế độ dòng lệnh, tôi không cần luồng riêng biệt đó.
Edward Falk

27

Lấy biểu mẫu Câu hỏi thường gặp về chủ đề Java Style Code :

H: Sự khác biệt giữa phương thức start () và run () của một luồng là gì?

Đáp: Các phương thức start () và run () riêng biệt trong lớp Thread cung cấp hai cách để tạo các chương trình phân luồng. Phương thức start () bắt đầu thực thi luồng mới và gọi phương thức run (). Phương thức start () trả về ngay lập tức và luồng mới thường tiếp tục cho đến khi phương thức run () trả về.

Phương thức run () của lớp Thread không làm gì cả, vì vậy các lớp con nên ghi đè phương thức bằng mã để thực thi trong luồng thứ hai. Nếu một Luồng được khởi tạo bằng đối số Runnable, phương thức run () của luồng sẽ thực thi phương thức run () của đối tượng Runnable trong luồng mới để thay thế.

Tùy thuộc vào bản chất của chương trình luồng của bạn, việc gọi phương thức Thread run () trực tiếp có thể cho kết quả tương tự như gọi qua phương thức start (), nhưng trong trường hợp sau, mã thực sự được thực thi trong một luồng mới.


thread's run() method executes the run() method of the Runnable object in the new thread instead.Điều đó không đúng (hoặc ít nhất là mã nguồn Java 8 của tôi nói khác), nhưng rất tiếc liên kết có vẻ bị hỏng nên thay vào đó tôi báo cáo lỗi ở đây.
kajacx

1
@Tomalak, Điều này không trả lời câu hỏi được hỏi. Câu hỏi không phải là yêu cầu sự khác biệt, mà hỏi về các trường hợp sử dụng, theo đó chúng tôi sẽ gọi thread.run()thay vì thread.start().
Pacerier

24

Việc thực thi thread.run()không tạo ra một mã mới Threadtrong đó mã của bạn được thực thi. Nó chỉ thực thi mã trong Luồng hiện tại mà từ đóthread.run() mã được gọi.

Việc thực thi thread.start()tạo ra một luồng cấp hệ điều hành mới trong đó run()phương thức được gọi.

Về bản chất:

Lập trình đơn luồng → Gọi trực tiếp run()phương thức

Lập trình đa luồng → Gọi start()phương thức

Hơn nữa, như những người khác đã đề cập, 'thử nghiệm' dường như là trường hợp khuyến khích duy nhất trong đó bạn có thể gọi run()trực tiếp từ mã của mình.


13

Điều này đã được ám chỉ, nhưng cần phải nói rõ: việc tạo một đối tượng Thread mới chỉ để gọi phương thức run () của nó là không cần thiết phải tốn kém và phải là một dấu hiệu lớn. Sẽ là một thiết kế tách rời, tốt hơn nhiều để tạo một Runnable impl và (a) gọi nó là phương thức run () trực tiếp nếu đó là hành vi mong muốn hoặc (b) xây dựng một Thread mới với Runnable đó và bắt đầu Thread.

Tốt hơn nữa, để tách nhiều hơn nữa, hãy xem Executorgiao diện và khuôn khổ trong JDK 5 và mới hơn. Nói tóm lại, điều này cho phép bạn tách riêng việc thực thi tác vụ (cá thể Runnable) khỏi cách nó được thực thi (triển khai Executor, có thể thực thi Runnable trong Luồng hiện tại, trong một Luồng mới, sử dụng một Luồng hiện có từ một nhóm, và không).


9

Gọi thread.start(), nó sẽ lần lượt gọi thread.run(). Không thể nghĩ ra trường hợp khi bạn muốn bỏ qua thread.start()và đi thẳng đếnthread.run()


3
Trong quá trình thử nghiệm là trường hợp hợp pháp duy nhất tôi có thể nghĩ đến. Nếu không, nội dung của run () phải nằm trong một phương thức riêng biệt được gọi bằng run hoặc bằng cách khác.
Bill the Lizard

9

Các phương thức start()và riêng biệt run()trong lớp Thread cung cấp hai cách để tạo các chương trình phân luồng. Các start()phương pháp bắt đầu thực hiện các đề mới và gọi run()phương thức. Các start()phương thức trả về ngay lập tức và các chủ đề mới thường tiếp tục cho đến khi run()trở về phương pháp.

run()Phương thức của lớp Thread không làm gì cả, vì vậy các lớp con nên ghi đè phương thức bằng mã để thực thi trong luồng thứ hai. Nếu một Luồng được khởi tạo bằng đối số Runnable, run()phương thức của luồng sẽ thực thi run()phương thức của đối tượng Runnable trong luồng mới để thay thế.

Tùy thuộc vào bản chất của chương trình luồng của bạn, việc gọi run()phương thức Luồng trực tiếp có thể cho kết quả tương tự như gọi qua start()phương thức, nhưng trong trường hợp sau, mã thực sự được thực thi trong một luồng mới.

tài liệu tham khảo


Giống như câu trả lời của Tomalak !! Nếu bạn đã tham khảo từ một số nơi, hãy đề cập đến điều đó !!
Barry

The start() method returns immediately and the new thread normally continues until the run() method returns.Nếu start()lợi nhuận ngay lập tức như thế nào đến sự run()tiếp tục chạy cho rằng nó được gọi là bản thân từstart()
KNU

7

Nếu Câu hỏi là - "tại sao phương thức bắt đầu luồng được gọi thay vì phương thức chạy trực tiếp" thì tôi đã trả lời bằng một đoạn mã ví dụ bên dưới. Hy vọng rằng làm rõ. Trong ví dụ dưới đây:

/*
By calling t1.start(), 
we are getting the main calling thread returned immediately 
after the t1.start() called and is ready to proceed for other 
operations.And the thread t1 starts executing the run method of the object r. 
Hence the the output will be:

      I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000

      I am done executing run method of testThread

*/


/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
 its like a regular method call and the main thread will not return until the run method completes, 
 hence the output will be:

         I am done executing run method of testThread

         I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000

*/


class testThread implements Runnable{

 public void run()
 {
     for(int i=0;i<1000000;i++){} //a simple delay block to clarify.

     System.out.println("I am done executing run method of testThread");

 }  
}

public class mainClass{

   public static void main(String [] args)
    {
          testThread r = new testThread();
          Thread t1 = new Thread(r);
          t1.start();  /* Question is: can we call instead t1.run() */  
          System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");

    }
}

5

Khi bạn muốn nó chạy đồng bộ. Việc gọi phương thức run sẽ không thực sự cung cấp cho bạn đa luồng. Phương thức bắt đầu tạo một luồng mới gọi phương thức chạy.


3

Nếu bạn muốn thực thi nội dung của run () giống như bất kỳ phương thức nào khác. Tất nhiên, không phải để bắt đầu một chủ đề.


3

Giả sử rằng bạn biết cách sử dụng phương thức bắt đầu và chạy tức là đồng bộ so với không đồng bộ; phương pháp run có thể được sử dụng chỉ để kiểm tra chức năng.

Thêm vào đó, trong một số trường hợp, cùng một lớp luồng có thể được sử dụng ở hai nơi khác nhau với các yêu cầu chức năng đồng bộ và không đồng bộ bằng cách có hai đối tượng khác nhau với phương thức chạy của một người và phương thức bắt đầu của người khác được gọi.


2

Ít nhất trong JVM 1.6., Có một chút kiểm tra và chạy được gọi là nguyên bản:

 public synchronized void start() {
        /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added 
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
    }

    private native void start0();

2

Chỉ cần lưu ý các nhận xét tuyệt vời ở trên: đôi khi bạn viết mã đa luồng sử dụng phương thức "bắt đầu" để chạy các luồng khác nhau. Bạn sẽ thấy dễ dàng hơn nhiều nếu sử dụng "run" (thay vì "start) để gỡ lỗi vì nó làm cho mã chạy đồng bộ và gỡ lỗi dễ dàng hơn nhiều.


-1
public class TestClass implements Runnable {
    public static void main(String[] args) {
        TestClass tc = new TestClass();

        Thread t1 = new Thread(tc);
        System.out.println("Before Starting Thread " + Thread.currentThread().hashCode());
        t1.start();
        System.out.println("After Starting Thread " + Thread.currentThread().hashCode());
    }

    @Override
    public void run() {
        System.out.println("TestClass Run method is  Running with thread " + Thread.currentThread().hashCode());        
    }
}

Hi Frnz, Check Out và Run ví dụ trên để hiểu rõ lần đầu tiên chạy với t1.start () và xem hashcode và thời gian tiếp theo với t1.run () và hashcodes chk
Avatar Girase

Câu hỏi của bạn ở đâu?
Amen Jlili
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.