Running code on the main thread from a secondary thread?

前端 未结 5 504
灰色年华
灰色年华 2020-12-05 10:23

This is a general Java question and not an Android one first off!

I\'d like to know how to run code on the main thread, from the context of a secondary thread. For e

相关标签:
5条回答
  • 2020-12-05 10:42

    There is no universal way to just send some code to another running thread and say "Hey, you, do this." You would need to put the main thread into a state where it has a mechanism for receiving work and is waiting for work to do.

    Here's a simple example of setting up the main thread to wait to receive work from other threads and run it as it arrives. Obviously you would want to add a way to actually end the program and so forth...!

    public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
    
    public static void main(String[] args) throws Exception {
        new Thread(new Runnable(){
            @Override
            public void run() {
                final int result;
                result = 2+3;
                queue.add(new Runnable(){
                    @Override
                    public void run() {
                        System.out.println(result);
                    }
                });
            }
        }).start();
    
        while(true) {
            queue.take().run();
        }
    }
    
    0 讨论(0)
  • 2020-12-05 10:55

    You may want to use the 'even dispatching thread' where most event driven things happen. If you are using swing then:

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Your code here.
            }
        });
    

    Or create a class that implements Runnable and pass it into invokeLater().

    0 讨论(0)
  • 2020-12-05 10:57

    An old discussion, but if it is a matter of sending request to the main thread (an not the opposite direction) you can also do it with futures. The basic aim is to execute something in background and, when it is finished, to get the result:

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // create the task to execute
        System.out.println("Main: Run thread");
        FutureTask<Integer> task = new FutureTask<Integer>(
                new Callable<Integer>() {
    
                    @Override
                    public Integer call() throws Exception {
                        // indicate the beginning of the thread
                        System.out.println("Thread: Start");
    
                        // decide a timeout between 1 and 5s
                        int timeout = 1000 + new Random().nextInt(4000);
    
                        // wait the timeout
                        Thread.sleep(timeout);
    
                        // indicate the end of the thread
                        System.out.println("Thread: Stop after " + timeout + "ms");
    
                        // return the result of the background execution
                        return timeout;
                    }
                });
        new Thread(task).start();
        // here the thread is running in background
    
        // during this time we do something else
        System.out.println("Main: Start to work on other things...");
        Thread.sleep(2000);
        System.out.println("Main: I have done plenty of stuff, but now I need the result of my function!");
    
        // wait for the thread to finish if necessary and retrieve the result.
        Integer result = task.get();
    
        // now we can go ahead and use the result
        System.out.println("Main: Thread has returned " + result);
        // you can also check task.isDone() before to call task.get() to know
        // if it is finished and do somethings else if it is not the case.
    }
    

    If your intention is to do several stuff in background and retrieve the results, you can set some queues as said above or you can split the process in several futures (starting all at once or starting a new one when needed, even from another future). If you store each task in a map or a list, initialized in the main thread, you can check the futures that you want at anytime and get their results when they are done.

    0 讨论(0)
  • 2020-12-05 11:01

    In case you are on Android, using a Handler should do the job?

    new Handler(Looper.getMainLooper()).post(new Runnable () {
        @Override
        public void run () {
            ...
        }
    });
    
    0 讨论(0)
  • 2020-12-05 11:04

    If you're using JavaFX, which I highly recommend, then you can use

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                alert(text);
            }
        });
    

    from within your non-UI thread, and the runnable will executed from the UI thread on return from your thread.

    0 讨论(0)
提交回复
热议问题