Thread start () ve Runnable run () arasındaki fark nedir


224

Diyelim ki şu iki Runnable'ımız var:

class R1 implements Runnable {
    public void run() {  }
    
}

class R2 implements Runnable {
    public void run() {  }
    
}

O zaman bu arasındaki fark nedir:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();

    r1.run();
    r2.run();
}

Ve bu:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();
}

Yanıtlar:


309

İlk örnek: Birden fazla iş parçacığı yok. Her ikisi de tek (mevcut) iş parçacığında yürütülür. İş parçacığı oluşturma yok.

R1 r1 = new R1();
R2 r2 = new R2();

r1ve arabirimi uygulayan ve böylece yöntemi uygulayan r2iki farklı sınıf nesnesidir. Aradığınızda geçerli iş parçacığı bunu hayata geçiriyoruz.Runnablerun()r1.run()

İkinci örnek: İki ayrı iplik.

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1ve t2sınıfın nesneleridir Thread. Aradığınızda t1.start(), yeni bir iş parçacığı başlatır ve bu yeni iş parçacığı içinde onu yürütmek için dahili run()yöntemini çağırır r1.


5
Biz Thread # start () çağırmadan önce, os thread ile ilgili hiçbir şey olmadığını düşünebilir miyim? Sadece bir java nesnesidir.
Jaskey

4
Bu belgelere göre doğrudur. Belgelere uygun iplik nesnesi başlatma kodunu kontrol edin. Ayrıca kaynak kodunda, start()os iş parçacığı ile ilgili şeylerin gerçekleşmesi gereken bir natvie yöntemi çağırıyor.
Bhesh Gurung

3
İş parçacığı oluşturucu dokümanları burada . İş parçacığı nesnesi başlatma kaynağı burada . start()yöntem kaynağı burada .
Bhesh Gurung

92

Sadece run()doğrudan çağırırsanız, diğer yöntem çağrıları gibi, çağrı dizisinde yürütülür. Thread.start()runnable'ın runyönteminin paralel olarak yürütülmesi için yeni bir iş parçacığı oluşturmak gerekir .


2
Hotspot JVM'de java iş parçacığı ve yerel iş parçacığı arasında doğrudan bir eşleme vardır. Thread.start()invocation, thread durumunun yeni durumdan Runnable durumuna geçmesini sağlar . Runnable, iş parçacığının çalıştığı anlamına gelmez. Doğal diş başladığında, doğal diş çağırır run()parçacığı durum değişikliği yapan bir Java iplik, yöntemi çalıştırılabilir için çalıştırma . İş parçacığı sona erdiğinde, hem yerel hem de Java iş parçacığı için tüm kaynaklar serbest bırakılır.
aşırı döviz değişimi

@overexchange Durum değişikliği ile ilgili materyali nerede bulabilirim?
twlkyao

73

Fark yani Thread.start()çağıran bir iş parçacığı başlatır run()iken, yöntem Runnable.run()sadece çağırır run()geçerli iş parçacığı üzerinde yöntem.


35

Aradaki fark , program çağrıları start()yöntemi olduğunda , yeni bir evre oluşturulur ve içerideki kod yeni evrede run()yürütülürken, yöntemi doğrudan çağırırsanız yeni bir evre oluşturulmaz ve içerideki kod doğrudan geçerli evrede yürütülür.run()run()

Başka bir fark arasındaki start()ve run()Java dizisindeki böyle olduğunu olamaz diyoruz start()iki kez. Başladıktan sonra, ikinci start()çağrı IllegalStateExceptionJava'ya atılacak , ancak sıradan bir yöntem run()olduğu için yöntemi birkaç kez çağırabilirsiniz .


21

Aslında Thread.start()yeni bir iş parçacığı oluşturur ve kendi yürütme senaryosuna sahiptir.

Thread.start()run()yöntemi zaman uyumsuz olarak çağırır , bu da yeni İş parçacığının durumunu Runnable olarak değiştirir.

Ancak Thread.run()yeni bir iş parçacığı oluşturmaz. Bunun yerine, geçerli çalışan iş parçacığında run yöntemini eşzamanlı olarak yürütür.

Kullanıyorsanız, Thread.run()o zaman çok iş parçacığının özelliklerini kullanmıyorsunuz demektir.


8

invoke run(), diğer yöntem çağrıları gibi, çağıran evre üzerinde yürütülüyor. oysa Thread.start()yeni bir evre oluşturur. çağırmak run()programlı bir hatadır.


7

run()Ana yöntemde yaparsanız , ana yöntemin iş runparçacığı çalıştırmak istediğiniz iş parçacığı yerine yöntemi çağırır .

start()Yöntem yeni iş parçacığı oluşturur ve kendisi için run()bir yöntem yapılmalıdır


'Ana yöntemin' bununla hiçbir ilgisi yoktur.
Lorne Marquis

3
@EJP, mainyazar tarafından çağrı yöntemi anlamına geliyordu. Cevabı oldukça iyi. +1 ;-)
dom_beau

1
@dom_beau Eğer demek istediği buysa, bunu söylemeliydi. Söylediği yanlıştı. Bu cevap hakkında 'oldukça iyi' bir şey yok. Bu sadece karışık bir karmaşa.
Lorne Marquis

5

t.start() yeni bir iş parçacığı istediğinizde kitaplığın kodunuzu çağırması için sağladığı yöntemdir.

r.run()Bu yöntem size temin kütüphane aramaya içinde yeni iş parçacığı.


Bu cevapların çoğu büyük resmi kaçırır, yani Java dili söz konusu olduğunda, diğer iki yöntem arasında t.start()ve r.run()daha fazla fark yoktur .

İkisi de sadece yöntem. Her ikisi de onları adlandıran iş parçacığında çalışır . Her ikisi de yapmak için kodlandıkları her şeyi yaparlar ve sonra ikisi de hala aynı iş parçacığında arayanlara geri döner.

En büyük fark için kod çoğu olmasıdır t.start()olan yerli , çoğu durumda, kod iken kod r.run()Java saf olacak. Ama bu bir fark değil. Kod koddur. Yerel kodu bulmak daha zordur ve bulduğunuzda anlaşılması daha zordur, ancak yine de bilgisayara ne yapması gerektiğini söyleyen koddur.

Peki ne yapar t.start()?

Yeni bir yerel iş parçacığı oluşturur, bu iş parçacığının aranmasını düzenler t.run()ve işletim sistemine yeni iş parçacığının çalışmasına izin vermesini söyler. Sonra geri döner.

Ve ne yapar r.run()?

Komik olan şey, bu soruyu soran kişi , onu yazan kişidir . r.run()ne yaparsanız yapın (yani onu yazan geliştirici) bunu yapmak için tasarladı.


4

Thread.start()kod iş parçacığı ile zamanlayıcı kaydeder ve zamanlayıcı run()yöntemi çağırır . Ayrıca, Threadclass while Runnablebir arayüzdür.


3

Puanın, üyelerin yaptığı iyi, bu yüzden sadece bir şeyler eklemek istiyorum. Mesele şu ki, JAVA Çoklu kalıtımı desteklemiyor. Ancak, başka bir A sınıfından B sınıfı türetmek istiyorsanız, ancak yalnızca bir Sınıftan türetebilirsiniz. Şimdi sorun, her iki sınıftan da "türetilmesi": A ve Thread. Bu nedenle Çalıştırılabilir Arabirimi kullanabilirsiniz.

public class ThreadTest{
   public void method(){
      Thread myThread = new Thread(new B());
      myThread.start;
   }
}

public class B extends A implements Runnable{...

runnable - bir arayüz ve Thread - bir sınıf
Pinky Walve

1

run()Yöntemi doğrudan çağırırsanız, yöntem run()arayan iş parçacığının bir parçası olarak yürütüldüğünden, çoklu iş parçacığı oluşturma özelliğini kullanmazsınız .

start()Thread üzerinde yöntemi çağırırsanız , Java Virtual Machine run () yöntemini çağırır ve iki iş parçacığı aynı anda çalışır - Current Thread ( main()örneğin) ve Other Thread ( r1örneğinizde Runnable ).

Thread sınıfındastart() yöntemin kaynak koduna göz atın

 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    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();

Yukarıdaki kodda, run()yönteme çağırmayı göremezsiniz .

private native void start0()çağrı run()yönteminden sorumludur . JVM bu yerel yöntemi yürütür.


0

İlk durumda sadece ve nesnelerinin run()yöntemini çağırıyorsunuz .r1r2

İkinci durumda aslında 2 yeni Konu oluşturuyorsunuz!

start()bir run()noktada arayacak !


7
Aslında start (), run () öğesini çağırmaz: eğer yaptıysa, run () yöntemi start () adlı aynı iş parçacığı tarafından yürütülür. Start () yönteminin yapacağı run () yöntemini çağıracak bir iş parçacığı oluşturmaktır.
Bruno Reis

0

run yöntemi: - Başlangıçta Runnable arabiriminde oluşturulan ve Thread sınıfının yanı sıra Thread alt sınıflarında (Thread'in kaynak kodunda Runnable uyguladığı gibi) ve Runnable arabiriminin diğer uygulama sınıflarında geçersiz kılınan soyut bir yöntemdir. - İş parçacığını (çalıştırılabilir nesne) yapmak istediği görevle yüklemek için kullanılır, böylece bu görevi yazmak için onu geçersiz kılarsınız.

start yöntemi: - Thread sınıfında tanımlanır. Bir Thread nesnesi 1- üzerinde start yöntemi çağrıldığında, start0 () adı verilen dahili olarak yerel (non-java) yöntemi çağırır; yöntem.

start0 (); yöntemi: bu noktada düşük işleme (bir iş parçacığı için yığın oluşturma ve iş parçacığı işlemci kuyruğunda tahsis etme) sorumludur.

2- İş parçacığı zamanlayıcısı, bir iş parçacığının (iş parçacığı önceliği ve işletim sistemi zamanlama algoritması) bir işlemciye girdiğine karar verdiğinde Runnable nesnesinde (geçerli Runnable iş parçacığı nesnesi mi yoksa Runnable nesnesinin mi geçirildiği) burada bir iş parçacığı Çalışan durumuna girer ve görevini yürütmeye başlar (çalışma yöntemi)


-2

Thread sınıfındaki ayrı start () ve run () yöntemleri, dişli programlar oluşturmak için iki yol sağlar. Start () yöntemi, yeni iş parçacığının yürütülmesini başlatır ve run () yöntemini çağırır. Start () yöntemi hemen döner ve yeni iş parçacığı normal olarak run () yöntemi dönene kadar devam eder.

Thread sınıfının 'run () yöntemi hiçbir şey yapmaz, bu nedenle alt sınıflar ikinci iş parçacığında yürütülecek kodu içeren yöntemi geçersiz kılmalıdır. Bir İş Parçacığı bir Runnable bağımsız değişkeniyle başlatılırsa, iş parçacığının run () yöntemi yeni iş parçacığında Runnable nesnesinin run () yöntemini yürütür.

İş parçacığı programınızın doğasına bağlı olarak, Thread run () yöntemini doğrudan çağırmak, start () yöntemi aracılığıyla çağrı yapmakla aynı çıktıyı verebilir, ancak ikinci durumda kod aslında yeni bir iş parçacığında yürütülür.


2
`Run () 'olarak adlandırmak, iş parçacığı programları oluşturmanın bir yolu değildir. Sadece bir yol var.
Lorne Marquis,

-2

İş parçacığı genişletilmiş sınıf ve Runnable uygular arabiriminin start () yöntemi çağrı run override yöntemi.

Ancak run () yöntemini çağırarak run yöntemini arar ancak Runnable arabirimini uygulayan sınıf Runnable'ın run () geçersiz kılma yöntemini çağırır.

ex .:

'

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class 
        //implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it 
        //didn't show any error.

a.start();//this call run() of Thread
b.start();//this call run() of Thread
}

class A implements Runnable{
@Override
    public void run() {
            System.out.println("A ");
    }
}

class B extends Thread {

    @Override
    public void run() {
            System.out.println("B ");
    }
}

'

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.