Four ways of multithreading

4 ways to implement Java multithreading to demonstrate the code

The first: inherit the Thread class method

1. Implement the Runnable class
2. Rewrite the run method
3. Create a thread object
4. Call the start method to start the thread




/**
 * @ClassName RunnableDemo
 * @Description TODO
 * @Author Hai
 * @Date 2020/12/12 11:29
 * @Version 1.0
 **/

//第一步:继承Thread
public class ThreadDemo extends Thread  {
    
    

    //票数
    private static Integer ticketNums = 0;

    @Override
    //第二步:重写run方法
    public void run(){
    
    
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("当前正在运行子线程---第"+i+"次");
        }
    }

    public static void main(String[] args){
    
    
        //第三步:创建一个线程对象
        ThreadDemo threadDemo = new ThreadDemo();
        //第四步:调用start()启动线程
        threadDemo.start();
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("正在运行主线程---第"+i+"次");

        }

    }
}



Click to run the main method:
when the thread is started, it will not be executed immediately, but will be scheduled and executed by the cpu. It
Insert picture description here
can be seen that the two for loops are executed in parallel

note! note!
Calling the start() method to start the thread, and directly calling the run() method to start it is the same as the ordinary calling method. The thread cannot be started, but it is equivalent to only calling an ordinary method!Insert picture description here

The second way: to implement the Runnable interface

1. Implement the Runnable interface
2. Rewrite the run method
3. Create a Thread object
4. Call the start method to start the thread



/**
 * @ClassName RunnableDemo
 * @Description TODO
 * @Author Hai
 * @Date 2020/12/12 11:29
 * @Version 1.0
 **/

//第一步:继承Thread
public class RunnableDemo implements Runnable{
    
    

    //票数
    private static Integer ticketNums = 0;
    
    @Override
    //第二步:重写run方法
    public void run(){
    
    
        while (true){
    
    
            //一共一百张票,抢完则跳出循环
            if(ticketNums>=100){
    
    
                break;
            }
            //获取当前线程名称并输出
            System.out.println(Thread.currentThread().getName()+"---拿到了第"+ ++ticketNums +"票");
        }
    }

    public static void main(String[] args){
    
    
        RunnableDemo runnableDemo = new RunnableDemo();
        //第三步:创建Thread对象   (为方便理解,以下不采用简写)
        Thread t1 = new Thread(runnableDemo ,"小明");
        Thread t2 = new Thread(runnableDemo ,"小红");
        Thread t3 = new Thread(runnableDemo ,"黄牛");
        //第四步:调用start方法启动线程
        t1.start();
        t2.start();
        t3.start();

    }
}


Click to run the main method:
when the thread is started, it will not be executed immediately, but will be scheduled and executed by the cpu
Insert picture description here

note! note! To declare again:
calling the start() method to start the thread, directly calling the run() method to start is the same as the ordinary calling method, the thread cannot be started, but it is equivalent to only calling an ordinary method!Insert picture description here

The third way: to implement the Callable interface

1. Implement the Callable interface
2. Rewrite the call() method
3. Create an execution service
4. Submit for execution
5. Get the result
6. Close the service


/**
 * @ClassName CallableDemo
 * @Description TODO
 * @Author Hai
 * @Date 2020/12/12 11:29
 * @Version 1.0
 **/

//第一步:实现Callable接口
public class CallableDemo implements Callable<Boolean> {
    
    

    private String name;

    public CallableDemo(String name) {
    
    
        this.name = name;
    }

    //第二部:重写call()方法
    @Override
    public Boolean call() {
    
    
        demo();
        return true;
    }

    public void demo(){
    
    
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("当前正在运行--"+ name +"  号线程--第"+i+"次");
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        CallableDemo setname1 = new CallableDemo("小明");
        CallableDemo setname2 = new CallableDemo("小红");

        //第三步:创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(2);
        //第四步:提交执行
        Future<Boolean> t1 = ser.submit(setname1);
        Future<Boolean> t2 = ser.submit(setname2);
        //第五步:获取结果
        Boolean b1 = t1.get();
        Boolean b2 = t2.get();
        //关闭服务
        ser.shutdownNow();
        System.out.println(b1);
        System.out.println(b2);

    }
}

Click to run the main method:
When the thread is started, it will not be executed immediately, but will be scheduled and executed by the cpu. Insert picture description here
Attention! note!
Calling the start() method to start the thread, and directly calling the run() method to start it is the same as the ordinary calling method. The thread cannot be started, but it is equivalent to only calling an ordinary method!
Insert picture description here
Remember! Remember!
Realize the Callable interface to create a thread. When the thread ends, you must close the thread service! It is best to use try/catch to put into finally, so as to avoid program exceptions causing the service to fail to close.

As shown in the figure below, when multiple threads operate on the same data, thread insecurity will occur.
This blog mainly explains several implementations of multithreading, and we will talk about thread safety later.Insert picture description here

The fourth: use thread pool to create

  何为线程池,顾名思义线程池就是一个 专门存放线程的一个池子
  提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回线程池中,这样可以避免频繁创建,销毁线程,实现重复利用。就像共享单车,当你使用完后别人还能使用
   能提高响应速度(减少了创建新线程的时间)
   降低资源消耗(重复利用线程池中线程,不需要每次都创建)
   便于线程的管理(...)
        corePoolSize:核心池的大小
        maximumPoolSize:最大线程数
        keepAliveTime:线程没有任务时最多保持多长时间后会终止
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * @ClassName TestPool 
 * @Description TODO
 * @Author Hai
 * @Date 2020/12/12 11:29
 * @Version 1.0
 **/

public class TestPool {
    
    
    public static void main(String[] args) {
    
    

        //3,创建服务,创建线程池
        //newFixedThreadPool 参数为:线程池大小
        ExecutorService service = Executors.newFixedThreadPool(10);

        //4,执行
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

        //5,关闭链接
        service.shutdown();
    }
}


//1,实现 Runnable接口
class MyThread implements  Runnable{
    
    
    //2,重写run方法编写线程体
    @Override
    public void run() {
    
    
        //输出当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}

The direct running method
Insert picture description here
shows that: 6 threads are executed, and the names of each thread are printed out normally

Review and summarize the creation of threads

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @ClassName TestPool 
 * @Description TODO
 * @Author Hai
 * @Date 2020/12/12 11:29
 * @Version 1.0
 **/


//回顾总结线程的创建
public class TheradNew {
    
    
    public static void main(String[] args) {
    
    
        //调用各个线程
        //继承Thread类启动方法
        new MyThread1().start();

        //实现Runnable接口启动方法
        new Thread(new MyThread2()).start();

        //实现Callable接口启动方法
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());
        new Thread(futureTask).start();
        try {
    
    
            //不要忘了实现Callable接口方式创建线程会有返回值
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
    }
}

//1丶继承Thread类
class MyThread1 extends Thread{
    
    
    @Override
    public void run(){
    
    
        System.out.println("继承Thread类创建线程");
    }
}

//2丶实现Runnable接口
class MyThread2 implements Runnable{
    
    
    @Override
    public void run(){
    
    
        System.out.println("实现Runnable接口创建线程");
    }
}

//3丶实现Callable接口
class MyThread3 implements Callable<Integer> {
    
    
    @Override
    public Integer call() throws Exception {
    
    
        System.out.println("实现Callable接口创建线程");
        return 100;
    }
}

After learning so many ways to create threads, which one is the best?

There is no accurate answer to this question for the time being. Various methods have their own advantages and disadvantages. It is best to use different creation methods according to different application scenarios. In the case of relatively high concurrency, the creation of thread pools is more suitable. It can create multiple threads in advance, put them into the thread pool, directly obtain them when used, and put them back into the thread pool after use, so as to avoid frequent creation and destruction of threads affecting resources and efficiency, and realize reuse. Of course, this is only a specific scenario with relatively high concurrency, and it cannot be said that the method of creating a thread pool is the best. This requires readers to make their own decisions based on the application scenario and the understanding of various creation methods. There is no best way, only the most suitable way.

end

Guess you like

Origin blog.csdn.net/weixin_49822811/article/details/111181215