【Turn】Introduction to the method of thread return value

Original address: http://smalltalllong.iteye.com/blog/1156407

Before Java 5, threads had no return value, and they often went to great lengths to "have" a return value, and the code was very difficult to write. Or simply bypass this hurdle and go the other way.
 
Now Java finally has tasks (aka threads) that return values.
 
Tasks that can return a value must implement the Callable interface, and similarly, tasks that do not return a value must implement the Runnable interface.
 
After executing the Callable task, you can obtain a Future object, and calling get on the object can obtain the Object returned by the Callable task.
 
Here is a very simple example:
Java code  
import java.util.concurrent.*;  
  
/**
* Java thread: a thread with a return value
*
* @author Administrator  
*/  
public class Test {  
        public static void main(String[] args) throws ExecutionException, InterruptedException {  
                //create a thread pool  
                ExecutorService pool = Executors.newFixedThreadPool(2);  
                //Create two tasks with return values  
                Callable c1 = new MyCallable("A");  
                Callable c2 = new MyCallable("B");  
                //Execute the task and get the Future object  
                Future f1 = pool.submit(c1);  
                Future f2 = pool.submit(c2);  
                //Get the return value of the task from the Future object and output it to the console  
                System.out.println(">>>"+f1.get().toString());  
                System.out.println(">>>"+f2.get().toString());  
                //Close the thread pool  
                pool.shutdown();  
        }  
}  
  
class MyCallable implements Callable{  
        private String oid;  
  
        MyCallable(String oid) {  
                this.oid = oid;  
        }  
  
        @Override  
        public Object call() throws Exception {  
                return oid+"The content returned by the task";  
        }  
}  
 Output result:
>>> Content returned by A task
>>> Content returned by task B

Process finished with exit code 0

It's very simple. To get a deeper understanding, you need to look at the API of the Callable and Future interfaces.

The second method:
Returning data from a thread is similar to passing data to a thread. Data can also be returned through class members and callback functions. But there are some differences between class members in returning data and passing data. Let's take a look at the differences between them.
  1. Return data through class variables and methods
  Using this method to return data requires that the data be obtained through class variables or methods after calling the start method. Let's first see what the result will be.
Java code  
package mythread;  
  
public class MyThread extends Thread  
{  
    private String value1;  
    private String value2;  
  
    public void run()  
    {  
        value1 = "Return data through member variable";  
        value2 = "Return data through member method";  
    }  
    public static void main(String[] args) throws Exception  
    {  
        MyThread thread = new MyThread();  
        thread.start();  
        System.out.println("value1:" + thread.value1);  
        System.out.println("value2:" + thread.value2);  
    }  
}  
 Running the above code may output the following results:
  value1: null
  value2: null
  From the above operation results, it is very abnormal. In the run method, values ​​have been assigned to value1 and value2, but the return is null. The reason for this is that the values ​​of value1 and value2 are output immediately after calling the start method, and the run method has not yet executed the statement that assigns values ​​to value1 and value2. To avoid this from happening, you need to wait for the run method to execute before executing the code that outputs value1 and value2. Therefore, we can think of using the sleep method to delay the main thread. For example, we can add the following line after thread.start(): sleep(1000);
  Doing this can make the main thread delay 1 second before continuing, but there is a problem with this, how do we know how long to delay. There are only two assignment statements in the run method of this example, and only one thread is created, so a delay of 1 second is enough, but if the statements in the run method are complex, this time is difficult to predict. Therefore, this method Not stable.
  Our purpose is to get the values ​​of value1 and value2, so we only need to judge whether value1 and value2 are null. If neither of them is null, both values ​​can be output. We can use the following code to achieve this:
  while (thread.value1 == null || thread.value2 == null);
   Using the above statement can be very stable to avoid this situation, but this method is too expensive system resources. You can imagine that if the code in the run method is very complex, it will take a long time for value1 and value2 to be assigned, so the while loop must continue to execute until both value1 and value2 are not empty. Therefore, we can make the following improvements to the above statement:
  while (thread.value1 == null || thread.value2 == null)
   sleep(100);
  In the while loop, after judging the values ​​of value1 and value2 for the first time, sleep for 100 milliseconds, and then judge these two values. This will take up less system resources.
   Although the above method can be solved well, Java's threading model provides us with a better solution, which is the join method. As discussed earlier, the function of join is to use threads to change from asynchronous execution to synchronous execution. When the thread becomes synchronous, it is no different from getting the return data from a normal method. Therefore, this problem can be solved more efficiently with code like the following:
Java code  
...  
thread.start();  
thread.join();  
...  
 After thread.join() is executed, the run method of the thread thread has exited, that is to say, the thread thread has ended. Therefore, after thread.join(), you can safely use any resource of the MyThread class to get the return data. 

The third:
Return data through callback function
  In the following example, the calculation result is passed to the thread through the process method of the Work class, but at the same time, three random numbers are obtained from the thread through the process method. Therefore, this method can both pass data to the thread and get data from the thread.
Java code  
package mythread;  
  
class Data  
{  
    public int value = 0;  
}  
class Work  
{  
    public void process(Data data, Integer numbers)  
    {  
        for (int n : numbers)  
        {  
            data.value += n;  
        }  
    }  
}  
public class MyThread3 extends Thread  
{  
    private Work work;  
  
    public MyThread3(Work work)  
    {  
        this.work = work;  
    }  
    public void run()  
    {  
        java.util.Random random = new java.util.Random ();  
        Data data = new Data();  
        int n1 = random.nextInt(1000);  
        int n2 = random.nextInt(2000);  
        int n3 = random.nextInt(3000);  
        work.process(data, n1, n2, n3); // use callback function  
        System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+"  
                + String.valueOf(n3) + "=" + data.value);  
    }  
    public static void main(String[] args)  
    {  
        Thread thread = new MyThread3(new Work());  
        thread.start();  
    }  
}  
 The process method in the above code is called the callback function. Essentially, callback functions are event functions. In the Windows API, callback functions are often used to exchange data between programs that call the API. Therefore, the process of calling the callback function is the most primitive process of raising an event. In this example, calling the process method to get the data is equivalent to raising an event in the run method

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326314635&siteId=291194637