Java Multithreading One of the four ways to create threads

  • 2021-07-18 07:52:59
  • OfStack

1. Implement Runnable interface, overload run (), no return value


package thread;
 
public class ThreadRunnable implements Runnable {
  public void run() {
    for (int i = 0; i < 10; i++) {
      System.out.println(Thread.currentThread().getName() + ":" + i);
    }
  }
}
 
 
package thread;
 
public class ThreadMain {
  public static void main(String[] args) throws Exception {
    ThreadRunnable threadRunnable1 = new ThreadRunnable();
    ThreadRunnable threadRunnable2 = new ThreadRunnable();
    ThreadRunnable threadRunnable3 = new ThreadRunnable();
    ThreadRunnable threadRunnable4 = new ThreadRunnable();
    Thread thread1 = new Thread(threadRunnable1);
    Thread thread2 = new Thread(threadRunnable2);
    Thread thread3 = new Thread(threadRunnable3);
    Thread thread4 = new Thread(threadRunnable4);
    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();
  }
}

2. Inherit the Thread class and override run ()

When using, by calling start () of Thread (this method is native), and then calling run () of the creation thread, the codes in run methods of different threads are executed alternately.

Insufficient: Because java is single inheritance, if the thread class already has a parent class, you cannot use this method to create threads.


public class ThreadEx extends Thread {
  public void run() {
    for (int i = 0; i < 10; i++) {
      System.out.println(Thread.currentThread() + ":" + i);
    }
  }
}
 
 
public class ThreadMain {
  public static void main(String[] args)
  {
    ThreadEx threadEx = new ThreadEx();
    threadEx.start();
  }
}

3. Implement Callable interface, create Thread thread with return value through FutureTask/Future, and execute it through Executor

Add: Similar to the implementation of Runnable interface, they are all implementation interfaces, but the difference is that this method has a return value and can obtain asynchronous execution results.

Extension: FutureTask is a class and Future is an interface.


package thread;
 
import java.util.concurrent.*;
 
public class ThreadCallable {
  public static void main(String[] args) throws Exception {
    FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
      public Integer call() throws Exception {
        for (int i = 0; i < 10; i++) {
          System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        return 1;
      }
    });
    Executor executor = Executors.newFixedThreadPool(1);
    ((ExecutorService) executor).submit(futureTask);
 
    // Get the thread execution state 
    System.out.println(Thread.currentThread().getName() + ":" + futureTask.get());
  }
}

4. Create ExecutorService using Executors, and refer to Callable or Future

Add: Applicable to thread pool and concurrency


package thread;
 
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
import static java.lang.Thread.sleep;
 
public class ThreadExecutors {
  private final String threadName;
 
  public ThreadExecutors(String threadName) {
    this.threadName = threadName;
  }
 
  private ThreadFactory createThread() {
    ThreadFactory tf = new ThreadFactory() {
      public Thread newThread(Runnable r) {
        Thread thread = new Thread();
        thread.setName(threadName);
        thread.setDaemon(true);
        try {
          sleep(1000);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        return thread;
      }
    };
    return tf;
  }
 
  public Object runCallable(Callable callable) {
    return Executors.newSingleThreadExecutor(createThread()).submit(callable);
  }
 
  public Object runFunture(Runnable runnable) {
    return Executors.newSingleThreadExecutor(createThread()).submit(runnable);
  }
}
 
 
 
package thread;
 
import java.util.concurrent.*;
 
public class ThreadMain {
  public static void main(String[] args) throws Exception {
    ThreadExecutors threadExecutors = new ThreadExecutors("callableThread");
    threadExecutors.runCallable(new Callable() {
      public String call() throws Exception {
        return "success";
      }
    });
 
    threadExecutors.runFunture(new Runnable() {
      public void run() {
        System.out.println("execute runnable thread.");
      }
    });
  }
}

5 The difference between Runnable interface and Callable interface

1) The two interfaces need to implement different method names, Runnable needs to implement the method for run (), Callable needs to implement the method for call (). 2) Implementation of the method return value is not 1, Runnable task after the execution of no return value, Callable task after the execution can be asynchronous calculation results. 3) Runnable can not throw an exception, Callable can throw an exception.

6 What is the meaning of Callable return value? Is it okay not to return value? When do you need to use return value?

First of all, Callable is the result state of thread asynchronous execution. If there are two threads A and B, and some business logic in B needs to determine that A is finished before it can proceed, then it is necessary to obtain the execution result of thread A.

Design background: A task requires a series of operations, such as copying a large amount of basic data, analyzing data and warehousing it. Due to the large number, the whole process needs to last about 10 seconds, and the user experience is poor, which needs to be reduced to 2 ~ 5s.

Design idea: After the decomposition process, the copied data is divided into one process, covering some data analysis functions at the same time, and the remaining data analysis is divided into one process, which is executed asynchronously. When the last task state is put into storage, all business operations need to be updated after execution, and the return value in the thread needs to be used at this time.


Related articles: