Java'da ayrı bir iş parçacığı olan bir yöntem nasıl çağırılır?


126

diyelim ki bir yöntemim var doWork(). Nasıl ayrı bir iş parçacığından (ana iş parçacığından değil) çağırırım.


Bu son ilgili soruda bazı örnekler var:
javada


Eşzamansız görevler için Reactive Java blog.danlew.net/2014/09/15/grokking-rxjava-part-1'e de göz atmak isteyebilirsiniz
Nathan Dunn

Yanıtlar:


138

RunnableArabirimi uygulayan bir sınıf oluşturun . Çalıştırmak istediğiniz kodu run()yönteme koyun - Runnablearayüze uymak için yazmanız gereken yöntem budur . "Ana" iş parçacığınızda, yeni bir Threadsınıf oluşturun, kurucuya kendi örneğinizin bir örneğini iletin Runnable, ardından start()onu çağırın . startJVM'ye yeni bir iş parçacığı oluşturmak için sihir yapmasını ve ardından runbu yeni iş parçacığında yönteminizi çağırmasını söyler.

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();
    }    
}

Başlamak için Java'nın eşzamanlılık eğitimine bir göz atın .

Yönteminiz sık sık çağrılacaksa, bu pahalı bir işlem olduğu için her seferinde yeni bir iş parçacığı oluşturmaya değmeyebilir. Bir tür iş parçacığı havuzu kullanmak muhtemelen en iyisi olacaktır. Göz at Future, Callable, Executorsınıfların java.util.concurrentpakette.


1
ya geçmek istediğiniz bir değişken varsa?
Louis Rhys

8
run()Orada bir değişken geçemez böylece yöntem, herhangi bir parametre alır. Bunu kurucuda iletmenizi öneririm - bunu göstermek için cevabımı düzenleyeceğim.
Noel M

1
1 yöntemi farklı bir iş parçacığında çağırmanın kısa bir yolu var mı? new Thread() { public void run() {myMethod();}}.start();Yolu biliyorum , bu en kısa olanı mı?
Steven Roose

@NoelM, sizinkiyle MANN'in cevabı arasındaki farkı açıklar mısınız?
Asif Mushtaq

2
MANN'in cevabı anonim bir gerçeklenimi kullanır Runnable- benimki genişleyen bir sınıftır Runnable. Ve bunu yaptığım için durumu örneklenen nesneye geçiren kendi kurucum var.
Noel M

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

veya

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

veya

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

veya

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

veya

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

Bu, yaptığım şey için mükemmel çalıştı. Gözlemci modelini kullanarak aynı anda bir web hizmeti çalıştırmak ve bir ilerleme çubuğunu güncellemek gerekiyordu.
dpi

@Ashish: Lütfen neyin ve neden düzenlendiğini açıklayın?
MANN

1
@AshishAggarwal: Birisi bunu yazardan izin almadan yaptığında bana garip geliyor!
MANN

@MANN, Thread parametresinde neden run metodunu kullandığınızı açıklar mısınız? daha iyi bir performans var mı?
Asif Mushtaq

1
İş parçacığını açıkça sonlandırmamız gerekiyor mu? İş parçacığını açıkça sonlandırmayarak bellek sızıntısı yaratma riski yok mu? Yoksa iş parçacığı ile bittiğinde run()mi sona eriyor ?
2016

59

Java 8'de bunu bir satır kodla yapabilirsiniz.

Yönteminiz herhangi bir parametre almıyorsa, bir yöntem referansı kullanabilirsiniz:

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

Aksi takdirde, yöntemi bir lambda ifadesinde çağırabilirsiniz:

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

bunu geri getirdiğim için üzgünüm ama bu tam olarak ne anlama ->geliyor?
Kyle

1
Lambda ifadesi oluşturmak için kullanılan sözdizimi budur. Daha fazla bilgi için şu bağlantılara bir göz atın: Java'da '->' ne yapar? ve Java ™ Öğreticileri - Lambda İfadeleri
Aaron Cohn

@AaronCohn harika şeyler adam! Java'daki iş parçacıklarına herhangi bir alternatif biliyor musunuz? Celery task queueAsenkron şeyler için kullanacağımız Python dünyasından geliyorum
CESCO

Java, İş Parçacıklarıyla uğraşmak için daha yüksek düzeyde soyutlamalara sahiptir , ancak belki daha çok Akka gibi bir şey arıyorsunuz ?
Aaron Cohn

8

Bir şeyleri çağırmak için daha hızlı bir seçenek (DialogBoxes ve MessageBoxes gibi ve iş parçacığı güvenli olmayan yöntemler için ayrı iş parçacıkları oluşturmak gibi) Lamba İfadesini kullanmak olacaktır.

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

3

Bir süre önce, JDK5 yürütme hizmetini kullanan ve arka planda belirli işlemleri yürüten basit bir yardımcı program sınıfı yazmıştım. DoWork () genellikle bir void dönüş değerine sahip olacağından, arka planda yürütmek için bu yardımcı program sınıfını kullanmak isteyebilirsiniz.

Bu yardımcı programı belgelediğim bu makaleye bakın .


6
Future ve Callable sizin için bu tür şeyleri yapar.
Amir Afghani

Evet yaparlar. buradaki fikir, zaman uyumsuz bir sarmalayıcının arkasındaki arayüzü soyutlamaktır.
raja kolluru

Bağlantı koptu (404).
palacsint

3

Bunu RxJava 2.x ile başarmak için şunları kullanabilirsiniz:

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

subscribeOn()Hangi zamanlayıcı yöntemi belirtir harekete çalıştırmak için - RxJava dahil olmak üzere birçok önceden tanımlı schedulers sahip Schedulers.io()havuz I / O işlemleri ve amaçlanan bir iş parçacığı olan Schedulers.computation()hangi işlemci yoğun operasyonlar için tasarlanmıştır.


3

En az Java 8 kullanıyorsanız, CompletableFuturerunAsync sınıfından yöntemi kullanabilirsiniz.

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

Bir sonuç döndürmeniz gerekiyorsa supplyAsyncbunun yerine kullanın

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