Bir parametre ile çalıştırılabilir mi?


178

Ben böyle bir runnable gerçekten var olmadığını biliyorum rağmen "bir parametre kabul Runnable" için bir ihtiyaç var.

Bu, uygulamamın tasarımında ve / veya yorgun beynimdeki zihinsel bir bloğun temel kusuruna işaret edebilir, bu yüzden burada temel OO ilkelerini ihlal etmeden aşağıdaki gibi bir şeyin nasıl gerçekleştirileceği hakkında bazı tavsiyeler bulmayı umuyorum :

  private Runnable mOneShotTask = new Runnable(String str) {
    public void run(String str) {
       someFunc(str);
    }
  };  

Yukarıdaki gibi bir şeyi nasıl gerçekleştireceğiniz hakkında bir fikriniz var mı?


7
Şimdi kullanabilirsiniz Consumer<T>.
Alex78191

1
Bu sorunun çeşitli cevaplarını okudum. Kimsenin projenize ihtiyacınız olan Runnables'ı (bir, iki, üç veya daha fazla argümanla) sadece uygun bir arayüz ekleyerek ekleyemeyeceğinizi garip görünüyor. Burada kimin ilgilendiği için yorumlu bir gist
Francesco Galgani

Bu "Java iş parçacığına nasıl parametre iletebilirim" ifadesinin kopyası DEĞİLDİR. Ve modern cevap, @ Alex78191'in dediği gibi: kullanımConsumer<T>
Epaga

Yanıtlar:


228

Aslında bunu yayınladığımdan beri neredeyse 9 yıl geçti ve dürüst olmak gerekirse, Java o zamandan beri birkaç gelişme yaptı. Orijinal cevabımı aşağıda bırakacağım, ancak insanların içinde ne olduğunu yapmasına gerek yok. 9 yıl önce, kod incelemesi sırasında neden yaptığını ve belki de onayladığını sorgulardım. Modern lambdalar mevcut olduğunda, antika bir yaklaşım öneren yüksek oy alan bir cevaba sahip olmak sorumsuzdur (tüm adaletle başlamak şüphe uyandırıyordu ...) Modern Java'da, kod incelemesi hemen reddedilecekti ve bu önerildi:

void foo(final String str) {
    Thread t = new Thread(() -> someFunc(str));
    t.start();
}

Daha önce olduğu gibi, bu konuyu anlamlı bir şekilde ele almak gibi ayrıntılar okuyucuya bir alıştırma olarak bırakılır. Ancak açıkçası, lambda kullanmaktan korkuyorsanız, çok iş parçacıklı sistemlerden daha da korkmalısınız.

Orijinal cevap, çünkü:

Bir yöntemi doğrudan yöntemde bildirebilirsiniz

void Foo(String str) {
    class OneShotTask implements Runnable {
        String str;
        OneShotTask(String s) { str = s; }
        public void run() {
            someFunc(str);
        }
    }
    Thread t = new Thread(new OneShotTask(str));
    t.start();
}

Hepinize teşekkür ederim! Önerilen çözümlerin hepsi aynı yaklaşıma işaret ediyor, ancak sadece bir tanesini kabul edebiliyorum. Bunu kendim bulamamaktan çok yorulmalıyım. Herkese +1.
uTubeFan

18
Aslında, çoğu insan bir yöntem içinde bir sınıf ilan edebileceğinizi bilmez. Bazıları bunun zayıf bir stil olduğunu düşünür. Sanırım bu bir zevk meselesi. :)
corsiKa

3
genel arabirim ResultRunnable <T> {genel void run (T sonucu); }
Roman M

46

Bir işleve koyabilirsiniz.

String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);

private Runnable createRunnable(final String paramStr){

    Runnable aRunnable = new Runnable(){
        public void run(){
            someFunc(paramStr);
        }
    };

    return aRunnable;

}

(Bunu kullandığımda, parametrem bir ID -> myRunnables hashmap'ı yapmak için kullandığım bir tamsayı kimliğiydi. Bu şekilde, bir işleyicideki farklı myRunnable nesnelerini göndermek / kaldırmak için hashmap'i kullanabilirim.)


3
Kodu paylaştığınız için teşekkürler - İnsanlar bunu sadece blabberlemek yerine yaptıklarında seviyorum. Bir soru - Bellek Sızıntısı söz konusu olduğunda yukarıdaki yaklaşım iyi mi? Geçtiğiniz tüm referanslar uygun şekilde imha edilecek mi?
nikib3ro

2
@ kape123 Cevap "duruma bağlıdır". RunnableYöntem tarafından döndürülen bir nesne herhangi bir yerde var olduğu sürece paramStr, muhtemelen çöp toplama için uygun olmayacaktır. Nesne varsa ancak bir daha asla çalıştırılamazsa, JIT (veya javac) onu kapsamdan kaldırmaya karar verebilir, ancak gelecekte değişebilecekleri için bu tür optimizasyonlara güvenmemeliyiz.
corsiKa

"Kodu paylaştığınız için teşekkür ederiz. İnsanlar bunu yapmaktan ziyade bunu yapmayı seviyorum." - ne?
Rob Grant

30
theView.post(new Runnable() {
    String str;
    @Override                            
    public void run() {
        par.Log(str);                              
    }
    public Runnable init(String pstr) {
        this.str=pstr;
        return(this);
    }
}.init(str));

Nesnenin kendisini döndüren init işlevi oluşturun ve parametreleri onunla başlatın.


1
Maalesef bir değişkene atayamayacak ve init () çağrısı
yapamayacaksınız

11

Runnable arabirimini uygulayan aşağıdaki sınıfı kullanıyorum . Bu sınıfla, bağımsız değişkenlerle kolayca yeni evreler oluşturabilirsiniz

public abstract class RunnableArg implements Runnable {

    Object[] m_args;

    public RunnableArg() {
    }

    public void run(Object... args) {
        setArgs(args);
        run();
    }

    public void setArgs(Object... args) {
        m_args = args;
    }

    public int getArgCount() {
        return m_args == null ? 0 : m_args.length;
    }

    public Object[] getArgs() {
        return m_args;
    }
}

2
Bu soyut sınıfı parametre ile bir runnable çalıştırmak için nasıl kullanırsınız?
EZDsIt

Ben parametresi (s) ile kullanım yapıcısı tercih public RunnableArg(Object... args) { setArgs(args); } sonra yerel sınıfını açıklar: class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } } ve kullanmak Thread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
GSD.Aaz

10

İki seçeneğiniz var:

  1. Adlandırılmış bir sınıf tanımlayın. Parametrenizi belirtilen sınıfın yapıcısına iletin.

  2. Anonim sınıfınızın "parametrenize" yakın olmasını sağlayın. Olarak işaretlediğinizden emin olun final.




5

Öncelikle burada yeni Runnable () 'a veya run ()' a iletilmek üzere bir argümana ihtiyaç duymak için burada ne yapmaya çalıştığınızı bilmek isterim. Genel yol, başlamadan önce üye değişkenleri ayarlayarak iş parçacıklarına veri (str) ileten bir Runnable nesnesine sahip olmak olmalıdır. Run () yöntemi daha sonra someFunc () komutunu yürütmek için bu üye değişken değerlerini kullanır

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.