“This is the second day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.

We often use multi-threaded development in our work. Today we will comb through several ways to create threads:

  1. Inherits the Thread class
  2. Implement the Runnable interface
  3. Create an implementation class for the Callable interface
  4. Created using ramda expressions (1.8)
  5. ForkJoinPool thread pool
  6. Inherit RecursiveAction, with no return value
  7. Inheriting RecursiveTask, with a return value
  8. Use the thread pool ThreadPoolExecutor
  9. Create the file by using the package Executors tool class

Thread class inheritance

Inherit the thread class and override the run method. Call the thread start method and wait for the JVM to allocate CPU time for the current thread to call the run method.

class Thread1 extends Thread {
    @Override  
    public void run(a) {
        //dosomething()
        System.out.println("Thread1"); }}Copy the code

Implement the Runnable interface

Implementation of the Runnable interface, rewrite the run method, the execution Thread needs to drop into the Runnable interface implementation class, call the Thread object start method to execute.

// Define a thread
class Runner1 implements Runnable {
    @Override  
    public void run(a) {
        //dosomething()
        System.out.println("Runner1"); }}// Thread execution
new Thread thread = new Thread(new Runner1());
thrad.start();
Copy the code

Create an implementation class for the Callable interface

Callable: A task that returns results and may throw an exception. Advantages:

  • Can get the task execution return value;
  • In combination with a Future, you can use the Future to track the results of asynchronous computations.
class Callable1 implements Callable {  
  @Override
  public String call(a) throws Exception {
    return "1";
  }
}

FutureTask stringFutureTask = new FutureTask<>(new Callable1());
stringFutureTask.run();
Copy the code

Creating with a stream

Essentially, the creation thread is represented by a Lambda, which is an instance of the Runnable interface.

Runnable runnable = () -> {
	System.out.println("createThreadForStream");
};
new Thread(runnable).start();
Copy the code

ForkJoinPool thread pool

ForkJoinPool: Java provides ForkJoinPool support for dividing a task into several “small tasks” for parallel computation and combining the results of several “small tasks” into a total result. ForkJoinPool is an ExecutorService implementation class, and therefore a special thread pool. ForkJoinPool provides the following two common constructors.

Public ForkJoinPool(int Parallelism) : Creates a ForkJoinPool that contains parallel threads of parallelism. Public ForkJoinPool() : Creates a ForkJoinPool using runtime.geTruntime ().availableProcessors() as parallelism.

After creating a ForkJoinPool instance, the ForkJoinPool submit(ForkJoinTask) or Invoke (ForkJoinTask task) can be invoked to perform a specific task. ForkJoinTask represents a parallel, merged task. ForkJoinTask is an abstract class that has two abstract subclasses, RecursiveAction and RecursiveTask.

  • RecursiveTask: represents a task that returns a value;
  • RecursiveAction: represents a task that returns no value;

We can create a thread with a RecursiveTask, RecursiveAction instance.

new ForkJoinPool().submit(new Thread1());
Copy the code

Inheriting RecursiveAction has no return value

We can create a thread object with no return value by inheriting RecursiveAction.

 class PrintTask extends RecursiveAction {  
   @Override
    protected void compute(a) {
        System.out.println("RecursiveAction subclass"); }}new ForkJoinPool().submit(new PrintTask());
Copy the code

Inherit RecursiveTask to get the return value

Inheriting RecursiveTask we can create a thread with a return value.

class CalcuteTask extends RecursiveTask {
  @Override
  protected Integer compute(a) {
    return 10;
  }
  
}

Executors.newSingleThreadExecutor().submit(new CalcuteTask());
ForkJoinTask submit = new ForkJoinPool().submit(new CalcuteTask());
Integer res = submit.get();
Copy the code

Using thread pools

ThreadPoolExecutor is the core utility class that we use to create a thread pool. The execute or Submit method submits the thread to execute the task and enter the thread pool. Wait for the thread pool to allocate resources for us to execute. And ThreadPoolExecutor provides very rich thread pool configuration parameters.

Creating a thread pool through ThreadPoolExecutor is also an approach advocated in the Alibaba Java programming specification.

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1.1.2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
threadPoolExecutor.execute(new Thread1());
Copy the code

Use and send package Executors

Executors are a typical factory method that wraps up ThreadPoolExecutor. There are a number of ways to create thread pools. Such as:

  • Public static ExecutorService newFiexedThreadPool(int Threads) Creates a thread pool with a fixed number of Threads.
  • Public static ExecutorService newCachedThreadPool() : Create a cacheable thread pool, and call execute to reuse previously constructed threads (if available). If no thread is available, a new thread is created and added to the pool. Terminates and removes threads from the cache that have not been used for 60 seconds.
  • Public static ExecutorService newSingleThreadExecutor() : Creates a single-threaded Executor.
  • Public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) Creates a thread pool that supports timed and periodic task execution. It can be used instead of the Timer class in most cases.
Executors.newSingleThreadExecutor().execute(new Thread1());
Executors.newFixedThreadPool(8).execute(new Thread1());
Executors.newWorkStealingPool(8).execute(new Thread1());
Executors.newCachedThreadPool().execute(new Thread1());
Executors.newSingleThreadScheduledExecutor().schedule(new Thread1(), 2, TimeUnit.SECONDS);
Executors.newScheduledThreadPool(8).schedule(new Thread1(), 2, TimeUnit.SECONDS);
Copy the code

conclusion

After the Java thread creation task, the UNDERLYING JVM creates a JavaThread and an OSThread, binding the Java thread object to the operating system kernel-state process.