Multiple Runnable in a single thread -java

2019-09-20 07:21发布

问题:

I am trying to have a bunch of runnable threads that can be started one at a time. Something like

First(new Thread() {
    public void run() {
        //do something

    }
});

Is what I'm trying to do impossible?

回答1:

You can use a single threaded Executor

ExecutorService service = Executors.newSingleThreadedPool();

service.submit(runnable1);
service.submit(runnable2);
service.submit(runnable3);


回答2:

Yes, just have multiple private methods:

public class FirstCaller {

   private void method1() { }
   private void method2() { }
   private void method3() { }

    public void someMethod() {
        First(new Thread() {
           public void run() {
                //do something
                method1();
                method2();
                method3();
            }
        });
    }
}

OR as pointed out by Ted Hopp

public class FirstCaller {
        public void someMethod() {
            new First(new Thread() {
               private void method1() { }
               private void method2() { }
               private void method3() { }

               public void run() {
                    //do something
                    method1();
                    method2();
                    method3();
                }
            });
        }
    }


回答3:

i want to have several runnables in one thread. they will be doing different things at different times.

This sounds like a bad design to me. If your class is doing different things at different times then it should be split into different classes.

If you are talking about re-using the same background thread to do different things, then I would use a single threaded pool as in @Peter's answer:

private ExecutorService threadPool = Executors.newSingleThreadedPool();
...
threadPool.submit(new First());
threadPool.submit(new Second());
threadPool.submit(new Third());
...
// when you are done submitting, always shutdown your pool
threadPool.shutdown();

The First, Second, and Third classes would implement Runnable. They can take constructor arguments if they need to share some state.



回答4:

If you want to start a few threads at the same time CountDownLatch is what you need. See an example here: http://www.javamex.com/tutorials/threads/CountDownLatch.shtml.



回答5:

Are you trying to execute multiple runnables sequentially in a single Thread? One after the other?

public class MultiRunnable implements Runnable {

    private Runnable runnable1;
    private Runnable runnable2;


    public MultiRunnable(Runnable runnable1, Runnable runnable2) {
        this.runnable1 = runnable1;
        this.runnable2 = runnable2;
    }

    @Override
    public void run() {
        runnable1.run();
        runnable2.run();
    }
}

You could then call (new Thread(new MultiRunnable(... , ...))).start();

This will execute the first Runnable first, and when that is finnished it will execute the second.


Or generalised to more Runnables:

import java.util.Arrays;
import java.util.List;

public class MultiRunnable implements Runnable {

    private List<Runnable> runnables;

    public MultiRunnable(Runnable... runnables) {
        this.runnables = Arrays.asList(runnables);
    }
    public MultiRunnable(List<Runnable> runnables) {
        this.runnables = runnables;
    }

    @Override
    public void run() {
        for(Runnable runnable : runnables)
            runnable.run();
    }
}


回答6:

The easiest thing to do is to define several Thread subclass instances and call the appropriate one depending on what you are trying to do.

However, if you really need a single Thread object that behaves differently in different circumstances, you can define a Thread subclass that has a state variable for controlling what it does.

class MyThread extends Thread {
    public enum Action { A, B, C }
    private Action mAction;
    public void run() {
        if (mAction == null) {
            throw new IllegalStateException("Action must be specified");
        }
        switch (mAction) {
        case A:
            methodA();
            break;
        case B:
            methodB();
            break;
        case C:
            methodC();
            break;
        }
    }
    public void setAction(Action action) {
        if (action == null) {
            throw new IllegalArgumentException("Action cannot be null");
        }
        mAction = action;
    }
    private void methodA() { ... }
    private void methodB() { ... }
    private void methodC() { ... }
}

You could then create your thread and before calling start(), call setAction, passing one of the Action values.

As an alternative to a state variable, the run() method could examine external variables to determine the choice of action. Whether this makes sense (and whether it would be better) depends on your application.