Runnable with a parameter?

后端 未结 7 2463
后悔当初
后悔当初 2020-11-27 09:39

I have a need for a \"Runnable that accepts a parameter\" although I know that such runnable doesn\'t really exist.

This may point to fundamental flaw in the design

相关标签:
7条回答
  • 2020-11-27 10:12

    Since Java 8, the best answer is to use Consumer<T>:

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

    It's one of the functional interfaces, which means you can call it as a lambda expression:

    void doSomething(Consumer<String> something) {
        something.accept("hello!");
    }
    
    ...
    
    doSomething( (something) -> System.out.println(something) )
    
    ...
    
    0 讨论(0)
  • 2020-11-27 10:22

    I use the following class which implements the Runnable interface. With this class you can easily create new threads with arguments

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 10:29

    You have two options:

    1. Define a named class. Pass your parameter to the constructor of the named class.

    2. Have your anonymous class close over your "parameter". Be sure to mark it as final.

    0 讨论(0)
  • 2020-11-27 10:31

    I would first want to know what you are trying to accomplish here to need an argument to be passed to new Runnable() or to run(). The usual way should be to have a Runnable object which passes data(str) to its threads by setting member variables before starting. The run() method then uses these member variable values to do execute someFunc()

    0 讨论(0)
  • 2020-11-27 10:34

    You could put it in a function.

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

    (When I used this, my parameter was an integer ID, which I used to make a hashmap of ID --> myRunnables. That way, I can use the hashmap to post/remove different myRunnable objects in a handler.)

    0 讨论(0)
  • 2020-11-27 10:35

    Well it's been almost 9 years since I originally posted this and to be honest, Java has made a couple improvements since then. I'll leave my original answer below, but there's no need for people to do what is in it. 9 years ago, during code review I would have questioned why they did it and maybe approved it, maybe not. With modern lambdas available, it's irresponsible to have such a highly voted answer recommending an antiquated approach (that, in all fairness, was dubious to begin with...) In modern Java, that code review would be immediately rejected, and this would be suggested:

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

    As before, details like handling that thread in a meaningful way is left as an exercise to the reader. But to put it bluntly, if you're afraid of using lambdas, you should be even more afraid of multi-threaded systems.

    Original answer, just because:

    You can declare a class right in the method

    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();
    }
    
    0 讨论(0)
提交回复
热议问题