パラメータで実行できますか?


178

「パラメーターを受け入れるRunnable」が必要ですが、そのようなRunnableは実際には存在しないことを知っています。

これは、アプリの設計に根本的な欠陥があるか、疲れた脳の精神ブロックを示している可能性があるため、基本的なOOの原則に違反せずに、次のようなことを行う方法に関するアドバイスを見つけたいと思います。

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

上記のようなことを達成する方法はありますか?


7
これでを使用できますConsumer<T>
Alex78191

1
この質問に対するさまざまな回答を読みました。必要なRunnableをプロジェクトに追加できると誰も言わなかったのは奇妙に思えます(1つ、2つ、3つ以上の引数を使用して)、適切なインターフェイスを追加するだけです。興味のある方のためにここにコメント付きの要旨を作成しました:gist.github.com/jsfan3/3a66e711fd0fd233c5e4c467184adb7a
Francesco Galgani

これは、「Javaスレッドにパラメーターを渡す方法」と重複するものではありません。そして、最新の答えは、@ Alex78191が言うように:使用Consumer<T>
Epaga

回答:


228

さて、私が最初にこれを投稿してからほぼ9年が経過しました。正直なところ、Javaはそれ以来、いくつかの改善を加えてきました。元の答えは下に残しておきますが、そこにあることを人々がする必要はありません。9年前、コードレビュー中に、なぜ彼らがそれをしたのか、そしておそらくそれを承認したのかどうか疑問に思いました。現代のラムダを利用できるので、時代遅れのアプローチを推奨するような非常に投票された回答を持つことは無責任です(すべての公平において、最初から疑わしいものでした...)現代のJavaでは、そのコードレビューはすぐに拒否され、これは提案:

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

以前と同様に、そのスレッドを意味のある方法で処理するなどの詳細は、読者への課題として残されています。しかし、端的に言えば、ラムダの使用を恐れている場合は、マルチスレッドシステムをさらに恐れる必要があります。

元の答え、理由:

メソッド内でクラスを宣言できます

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

皆さん、ありがとうございました!提案されたすべての解決策は同じアプローチを指していますが、私は1つしか受け入れることができません。私はこれを自分で思いつくことができないのでとても疲れているに違いありません。+1から全員。
uTubeFan、2011年

18
実際、ほとんどの人は、メソッド内でクラスを宣言できることを知りません。それを貧弱なスタイルだと考える人もいます。それは好みの問題だと思います。:)
corsiKa

3
パブリックインターフェースResultRunnable <T> {public void run(T result); }
ロマンM

46

関数に入れることができます。

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;

}

(これを使用したとき、パラメーターは整数IDでした。これを使用してIDのハッシュマップを作成しました-> myRunnables。このようにして、ハッシュマップを使用して、ハンドラー内のさまざまなmyRunnableオブジェクトをポスト/削除できます。


3
コードを共有してくれてありがとう-私は人々がそれをするのではなく、それをするときに大好きです。1つの質問-メモリリークに関して、上記のアプローチは問題ありませんか?渡したすべての参照は適切に破棄されますか?
nikib3ro

2
@ kape123答えは「場合によります」です。Runnableメソッドによって返されるオブジェクトがどこかに存在する限り、paramStrおそらくガベージコレクションの対象にはなりません。オブジェクトが存在するが、再度実行できない場合、JIT(またはjavac)がオブジェクトをスコープから削除することを決定する可能性がありますが、将来的に変更される可能性があるため、このような最適化に依存すべきではありません。
corsiKa 2013

「コードを共有してくれてありがとう-人々がそんなことをするのではなく、それをするのが大好きです。」- 何?
ロブ・グラント

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

オブジェクト自体を返すinit関数を作成し、それを使用してパラメーターを初期化します。


1
残念ながら、それを変数に割り当ててinit()を呼び出すことはできません
Andrew Glukhoff

11

Runnableインターフェースを実装する次のクラスを使用します。このクラスを使用すると、引数を持つ新しいスレッドを簡単に作成できます

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
この抽象クラスを使用して、パラメーター付きのランナブルをどのように実行しますか?
EZDsIt 2016年

私は、パラメータ(複数可)とのコンストラクタを使用することを好む public RunnableArg(Object... args) { setArgs(args); } 、ローカルクラスについて説明します class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } } と、それを使用する Thread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
GSD.Aaz

10

次の2つのオプションがあります。

  1. 名前付きクラスを定義します。名前付きクラスのコンストラクターにパラメーターを渡します。

  2. 匿名クラスを「パラメーター」の近くに配置します。必ずとしてマークしてくださいfinal




5

最初に、引数をne​​w Runnable()またはrun()に渡す必要があるために、ここで何を達成しようとしているのかを知りたいと思います。通常の方法は、開始前にメンバー変数を設定することにより、data(str)をスレッドに渡すRunnableオブジェクトを持つことです。次にrun()メソッドはこれらのメンバー変数値を使用してsomeFunc()を実行します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.