Запуск с параметром?

Мне нужен "Runnable, который принимает параметр", хотя я знаю, что такого runnable на самом деле не существует.

Это может указывать на фундаментальный недостаток в дизайне моего приложения и / или умственный блок в моем усталом мозге, поэтому я надеюсь найти здесь несколько советов о том, как сделать что-то вроде следующего, не нарушая фундаментальные принципы ОО:

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

Любая идея, как сделать что-то подобное выше?

10 ответов

Решение

Вы можете объявить класс прямо в методе

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

Вы могли бы поместить это в функцию.

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 -> myRunnables. Таким образом, я могу использовать хэш-карту для публикации / удаления различных объектов myRunnable в обработчике.)

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

Создайте функцию инициализации, которая возвращает сам объект и инициализируйте параметры с ним.

Начиная с Java 8, лучший ответ - использовать Consumer<T>:

https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html

Это один из функциональных интерфейсов, что означает, что вы можете называть его лямбда-выражением:

void doSomething(Consumer<String> something) {
    something.accept("hello!");
}

...

doSomething( (something) -> System.out.println(something) )

...

Я использую следующий класс, который реализует интерфейс 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;
    }
}

У вас есть два варианта:

  1. Определить именованный класс. Передайте ваш параметр конструктору именованного класса.

  2. Ваш анонимный класс должен быть закрыт по вашему "параметру". Обязательно отметьте это как final,

Сначала я хотел бы знать, что вы пытаетесь выполнить, чтобы аргумент передавался в новый Runnable() или run(). Обычным способом должно быть наличие объекта Runnable, который передает данные (str) своим потокам, устанавливая переменные-члены перед запуском. Затем метод run () использует значения переменных-членов для выполнения someFunc().

Пока лучший способ:

      Consumer<String> oneShot = str -> {
    
   somefunc(str);
    
};

oneShot.accept("myString");
      /**
 * @author AbdelWadoud Rasmi
 * <p>
 * The goal of this class is to pass some parameters to a runnable instance, a good example is
 * after caching a file you need to pass the new path to user to do some work on it.
 */
public abstract class ParameterizedRunnable implements Runnable {
    private Object[] params;

    /**
     * @param params: parameters you want to pass the the runnable.
     */
    public ParameterizedRunnable(Object... params) {
        this.params = params;
    }

    /**
     * Code you want to run
     *
     * @param params:parameters you want to pass the the runnable.
     */
    protected abstract void run(Object... params);

    @Override
    public final void run() {
        run(params);
    }

    /**
     * setting params
     */
    public void setParams(Object... params) {
        this.params = params;
    }

    /**
     * getting params
     */
    public Object[] getParams() {
        return params;
    }
}

Создайте новый класс, реализующий Runnable. В этом классе вы можете расширить метод run(), создав абстрактные методы по вашему выбору.

      public abstract class CCallback implements Runnable {
@Override
public void run() {}

public abstract void run(Object any);

}

Теперь вы можете использовать этот класс в качестве функции обратного вызова следующим образом:

      public void whatever(CCallback callback) {
    String any = "any type of param";
    if (callback != null)
        callback.run(any);
}

Метод «Как угодно» теперь может завершить свою задачу до запуска нашего исполняемого файла:

      whatever(new CCallback() {
    @Override
    public void run(Object any) {
        // Here you can reach "any"
    }
});
Другие вопросы по тегам