One article recognizes 4 ways to create Java multithreading

What is a program?

  • Program: A set of instructions written in a certain language to accomplish a specific task. Refers to a static code .

What is a process?

  • Process: A process of executing a program , or a program that is running.
  • Note: Process is the unit of resource allocation, and the system will allocate different memory areas for each process when the system is running.

What is a thread?

  • Thread: A process can be further refined into a thread , which is an execution path within a program.
  • Note: Threads are the unit of scheduling and execution. Each thread has an independent running stack and program counter (pc), and the thread switching overhead is small.

Parallel and concurrent:

  • Parallel: Multiple CPUs perform multiple tasks simultaneously. For example: multiple people do different things at the same time.

  • Concurrency: A CPU (using time slices) executes multiple tasks simultaneously. When there are multiple threads in operation, if the system has only one CPU, it is impossible to really perform more than one thread at the same time, it can only divide the CPU running time into several time periods, and then allocate the time period to each thread Execution, when the thread code is running for a period of time, other threads are in a suspended state. This is concurrency

Then JAVA multi-thread implementation:

There are three main ways to achieve JAVA multithreading: inheriting the Thread class, implementing the Runnable interface, using ExecutorService, Callable, and Future to achieve multithreading that returns results. There is no return value after the first two ways of thread execution, only the last one has a return value.

(1) Inherit the Thread class to achieve multi-threading:

  • Although the method of inheriting the Thread class is listed as a multi-threaded implementation method, Thread is essentially an instance of the Runnable interface, which represents an instance of a thread, and the only way to start the thread is through the Thread class () Example method. The start () method is a native method that will start a new thread and execute the run () method. It is very simple to implement multi-threading in this way. You can directly extend Thread through your own class and overwrite the run () method to start a new thread and execute your own run () method.
  1. Create a subclass inherited from the Thread class
  2. Rewrite the run () of the Thread class-> declare the operation performed by this thread in run ()
  3. Create an object of a subclass of Thread class
  4. ** Call start () through this object **
public class ThreadTest extends Thread{ //创建一个继承于Thread类的子类

    //重写Thread类的run() --> 将此线程执行的操作声明在run()中
    @Override
    public void run(){
        System.out.println("这是:[" + getName() + "]的启动");
    }
    
    public static void main(String[] args) {
        //创建Thread类的子类的对象
        ThreadTest thread1 = new ThreadTest();
        ThreadTest thread2 = new ThreadTest();
        thread1.setName("线程一");//给线程设置名字
        thread2.setName("线程二");
        thread1.start();//通过线程子类对象调用start()
        thread2.start();
    }

}

Console result:

这是:[线程一]的启动。
这是:[线程二]的启动。
Process finished with exit code 0
可知启动了两个线程

(2) Implement the Runnable interface to achieve multi-threading:

  • If your own class has already extended another class, you cannot directly extend Thread. In this case, you must implement a Runnable interface:
  1. Create a class that implements the Runnable interface

  2. Implementation class to implement the abstract method in Runnable: run ()

  3. Create an object that implements the class

  4. Pass this object as a parameter to the constructor of the Thread class to create an object of the Thread class

  5. Call start () through an object of class Thread

//创建一个实现了Runnable接口的类
public class RunnableStart extends Thread implements Runnable {
    
    //实现类去实现Runnable中的抽象方法:run()
    @Override
    public void run() {
        System.out.println("这是:[" + Thread.currentThread().getName() + "]的启动");
    }

    public static void main(String[] args) {
//        创建实现类的对象
        RunnableStart runnableThread = new RunnableStart();
//        将实现类对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread thread1 = new Thread(runnableThread);
        Thread thread2 = new Thread(runnableThread);
        thread1.setName("Runnable方式线程一:");//设置线程的名字
        thread2.setName("Runnable方式线程二:");
//        通过Thread类的对象调用start()
        thread1.start();
        thread2.start();
    }
}

The console output:

这是:[Runnable方式线程二:]的启动
这是:[Runnable方式线程一:]的启动
Process finished with exit code 0

** Note: ** In fact, when a Runnable target parameter is passed to Thread, Thread's run () method will call target.run (), refer to the JDK source code:

public void run() {
  if (target != null) {
   target.run();
  }
}

(3) Implement callable method: (more powerful than implement Runnable method)

How to understand that the way to create a multi-thread by implementing the Callable interface is more powerful than the way to create a multi-thread by implementing the Runnable interface?

  • call () can have a return value.
  • call () can throw an exception and be caught by an outside operation to obtain the exception information
  • Callable supports generics
  1. Create an implementation class that implements Callable
  2. Implement the call method and declare the operation that this thread needs to perform in call ()
  3. Create Callable interface implementation class object
  4. Pass the object of this Callable interface implementation class to the FutureTask constructor to create an object of FutureTask
  5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create a Thread object, and call start ()
  6. Get the return value of the call method in Callable
//1.创建一个实现Callable的实现类
class CallThread implements Callable {
    //2.实现call方法,将此线程需要执行的操作声明在call()中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                sum += i;//计算100以内偶数之和
            }
        }
        return sum;
    }
}
public class ThreadTest {
    public static void main(String[] args) throws Exception {
        //3.创建Callable接口实现类的对象
        CallThread callThread = new CallThread();
        //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask = new FutureTask(callThread);
        //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        Thread thread = new Thread(futureTask);
        thread.start();
        //6.获取Callable中call方法的返回值
        //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
        Object sum = futureTask.get();
        System.out.println("实现Callable方式的返回值总和为:" + sum);
    }
}

Console result:

实现Callable方式的返回值总和为:2550
Process finished with exit code 0

(4) Use ExecutorService, Future (thread pool): to achieve multi-threaded return results:

method:

  1. Create a thread pool
  2. Create multiple tasks with return values
  3. Perform tasks and get Future objects
  4. Close thread pool
public class ThreadPoolTest {
    public static void main(String[] args) throws Exception {
        System.out.println("----程序开始运行----");
        Date start = new Date();//开始时间
        // 创建一个指定数量的线程池
        ExecutorService pool = Executors.newFixedThreadPool(10);
        // 创建多个有返回值的任务
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {//因为只设有限定10个线程
            Callable call = new TestCallable(i + " ");
            // 执行任务并获取Future对象
            Future f = pool.submit(call);
            list.add(f);
        }
        // 关闭线程池
        pool.shutdown();
        // 获取所有并发任务的运行结果
        for (Future f : list) {
            // 从Future对象上获取任务的返回值,并输出到控制台
            System.out.println(">>>" + f.get().toString());
        }
        Date end = new Date();//结束时间
        System.out.println("----程序结束运行----,程序运行时间【"
                + (end.getTime() - start.getTime()) + "毫秒】");//计算出来的总运行时间
    }
}

class TestCallable implements Callable<Object> {
    private String taskNum;//任务编号

    TestCallable(String taskNum) {
        this.taskNum = taskNum;
    }

    @Override
    public Object call() throws Exception {
        System.out.println(">>>" + taskNum + "任务启动");
        Date dateStart = new Date();//开始时间
        Thread.sleep(1000);//阻塞1000毫秒
        Date dateEnd = new Date();//结束时间
        long time = dateEnd.getTime() - dateStart.getTime();
        System.out.println(">>>" + taskNum + "任务终止");
        return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
    }
}

Console result:

----程序开始运行----
>>>0 任务启动
>>>3 任务启动
>>>2 任务启动
>>>1 任务启动
>>>4 任务启动
>>>5 任务启动
>>>6 任务启动
>>>8 任务启动
>>>7 任务启动
>>>9 任务启动
>>>4 任务终止
>>>2 任务终止
>>>1 任务终止
>>>3 任务终止
>>>5 任务终止
>>>0 任务终止
>>>0 任务返回运行结果,当前任务时间【1001毫秒】
>>>1 任务返回运行结果,当前任务时间【1001毫秒】
>>>2 任务返回运行结果,当前任务时间【1001毫秒】
>>>3 任务返回运行结果,当前任务时间【1001毫秒】
>>>4 任务返回运行结果,当前任务时间【1001毫秒】
>>>5 任务返回运行结果,当前任务时间【1001毫秒】
>>>8 任务终止
>>>6 任务终止
>>>7 任务终止
>>>6 任务返回运行结果,当前任务时间【1001毫秒】
>>>7 任务返回运行结果,当前任务时间【1001毫秒】
>>>9 任务终止
>>>8 任务返回运行结果,当前任务时间【1001毫秒】
>>>9 任务返回运行结果,当前任务时间【1001毫秒】
----程序结束运行----,程序运行时间【1005毫秒】

Thread pool mode code description:

Code explanation from author: wb_qiuquan.ying inexplicable seen today.

The Executors class in the above code provides a series of factory methods for creating a thread pool. The returned thread pools all implement the ExecutorService interface.
public static ExecutorService newFixedThreadPool (int nThreads)
creates a thread pool with a fixed number of threads.
public static ExecutorService newCachedThreadPool ()
creates a cacheable thread pool, and calling execute will reuse the previously constructed thread (if a thread is available). If no existing thread is available, a new thread is created and added to the pool. Terminate and remove those threads 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 scheduled and periodic task execution, and can be used to replace the Timer class in most cases.

ExecutoreService provides a submit () method, passing a Callable, or Runnable, and returning Future. If the Executor background thread pool has not yet completed the calculation of the Callable, this call returns the get () method of the Future object, which will block until the calculation is completed.


Summary: It is the creation of 4 kinds of threads, and a brief introduction to threads. If you have any other questions, please contact me.

Author public number: Xiaobai coding, everyone is welcome to pay attention to study together.

Insert picture description here

Published 13 original articles · won 41 · views 820

Guess you like

Origin blog.csdn.net/weixin_46146269/article/details/105613082