Lama
Lama

Reputation: 29

Return value from thread java

I am trying to receive serial data from Arduino and i want to store the value in a variable how can i do it ? I tried the code below but it is not storing the value of string in the array element t[0]

or is there a way to store reading from input stream ?

final String[] t = new String[1];
t[0]="0";
final Handler handler = new Handler();
stopThread = false;
buffer = new byte[1024];

Thread thread  = new Thread(new Runnable()
{
    public void run()
    {
        while(!Thread.currentThread().isInterrupted() && !stopThread)
        {
            try
            {
                int byteCount = inputStream.available();
                if(byteCount > 0)
                {
                    byte[] rawBytes = new byte[byteCount];
                    inputStream.read(rawBytes);
                    final String string=new String(rawBytes,"UTF-8");
                    handler.post(new Runnable() {
                        public void run()
                        {
                            textView.append(string);
                            t[0]=string;
                        }
                    });

                }
            }
            catch (IOException ex)
            {
                stopThread = true;
            }
        }
    }
});

thread.start();
return t[0];

Upvotes: 2

Views: 6825

Answers (3)

Amit Bera
Amit Bera

Reputation: 7325

You are setting the value of t[0] inside a new Thread which will run asynchronously. So it is possible that return t[0]; execute before another thread set the value of t[0]. You can use Thread#join write the code as below.

thread.start();
thread.join();
return t[0];

When you call Thread#join the parent thread will wait to finish the Thread on which you have called the join method. However, there are several mechanisms to do that like CountDownLatch and CyclicBarrier or Future but I think Thread#join is the easy and best suited for your use case.

Upvotes: 0

Cargeh
Cargeh

Reputation: 1029

In addition to TMH's answer, if you want to manage threads yourself or suggested code seems too complicated for now, here's a simpler way of using CompletableFuture:

CompletableFuture<Object> completableFuture = new CompletableFuture<>();

new Thread(new Runnable() {
    @Override
    public void run() {
        // computation, reading input streams, etc
        Object result = new Object();

        completableFuture.complete(result);
    }
}).start();

// get() will wait until it's completed
Object resultFromThread = completableFuture.get();

// further processing...

Upvotes: 3

THM
THM

Reputation: 671

Maybe better solution will be something like this:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ResultFromThread {

    public static void main(String... args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "something";
        });
        String result = cf.get();
    }

}

Instead of 'return "something";' you just need to add anything you want to do.

Another solution is (with handling an exception):

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ResultFromThread {

    public static void main(String... args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "something";//may also throw an exception
        }).handle((result, throwable) -> {
            if(throwable != null) {
                System.err.println(throwable);//do something with exception
            }
            return result;
        });
        String result = cf.get();
    }
}

Upvotes: 2

Related Questions