Java创建线程的七种方法,全网最全面总结~

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

前言

一、继承Thread重写run方法

二、实现Runnable接口重写run方法

三、使用匿名内部类创建 Thread 子类对象

四、使用匿名内部类实现Runnable接口

五、lambda表达式

六、实现Callable接口

七、使用线程池创建线程


前言

        属于基础的面试问题一定要能够回答全哦~


一、继承Thread重写run方法

        通过自定义一个类这里起名为MyThread继承Thread类重写run方法最后在main方法中new出MyThread实例调用这个实例的继承的Thread类的start方法创建一个线程。

Ps

1.创建出MyThread实例并不代表在系统真的创建一个线程只有调用start方法时才创建出一个新的线程新线程会执行run里的逻辑直到run里逻辑执行完线程就结束了

2.运行一次Java程序就启动了一个进程一个进程里至少会有一个线程这里JVM默认创建的线程就是main线程主线程main主线程和MyThread创建出来的新线程是“并发执行”的关系并发+并行也可以理解为同时执行各执行各的

3.直接调用run并没有创建线程只是在原来的线程中执行代码

代码如下

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承Thread重写run方法创建线程");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

二、实现Runnable接口重写run方法

        通过自定义一个类这里起名为MyRunnable实现Runnable接口重写run方法最后在main方法new出MyRunnable实例和Thread实例最后通过start方法创建并启动线程。

通俗理解

这里相当于把线程要干的活和线程本身分离开了使用MyRunnable这个自定义的类来表示“线程要完成的任务”这样做的目的就是为了“解耦合”假设未来有新的任务需要线程去执行那么通过这种方式代码改动就比较小。

代码如下

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现Runnable接口重写run方法");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

三、使用匿名内部类创建 Thread 子类对象

        直接创建Thread子类同时实例化出一个对象重写run方法最后通过start方法创建并启动线程。

代码如下

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("使用匿名内部类创建 Thread 子类对象");
            }
        };
        thread.start();
    }
}

四、使用匿名内部类实现Runnable接口

        通过使用使用匿名内部类实现Runnable接口作为Thread构造方法的参数最后通过start创建并启动线程

代码如下

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("使用匿名内部类实例Runnable接口作为构造参数");
            }
        });
        thread.start();
    }
}

五、lambda表达式

        lambda本质上就是一个“匿名函数”()表示函数的形参{}表示函数体->特殊语法表示它是lambda表达式(->是从C++那里抄来的)。

代码如下

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
           System.out.println("使用lambda表示创建线程");
        });
        thread.start();
    }

}

六、实现Callable接口

        通过自定义类这里起名为MyCallable实现Callable接口重写call方法call方法可以理解为线程需要执行的任务并且带有返回值这个返回表示一个计算结果如果无法计算结果则引发Exception异常如下源码英文解释

        接着创建Callable实例使用FutrueTast类包装Callable对象FutureTask是一个包装器需要接收Callable实例来创建并且有两个构造函数一个参数只有Callable对象另一个参数不仅有Callable对象还有一个泛型的result参数详细解释如下源码

最后使用FutureTask对象作为Thread的构造参数通过start方法创建并启动线程

注意这里可以用get方法获取线程执行后的返回值。

代码如下

class MyCallableTest implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("创建线程:" + Thread.currentThread().getName());
        return 2;
    }
}

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> task = new FutureTask<>(new MyCallableTest());
        Thread thread = new Thread(task);
        thread.start();
        System.out.println("创建线程的返回结果为:" + task.get());
    }

}

七、使用线程池创建线程

        在Java中线程池的本体叫ThreadPoolExecutor他的构造方法写起来十分麻烦为了简化构造方法标准库就提供了一系列工厂方法简化使用

什么是工厂模式

        工厂模式将创建产品实例的权利移交工厂我们不再通过new来创建我们所需的对象而是通过工厂来获取我们需要的产品。降低了产品使用者与使用者之间的耦合关系

也就是说这里创建线程池没有显式new而是通过Executors这个静态方法newCaChedThreadPool来完成的

常见用法

        线程池的单纯使用很简单使用submit方法把任务提交到线程池中即可线程池中会有线程来完成这些任务

代码如下

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Pool {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        pool.submit(new Runnable() {
            @Override
            public void run() {
                //执行业务逻辑
                for(int i = 1; i <= 100; i++) {
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行了任务" + i + "~");
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                //执行业务逻辑
                for(int i = 101; i <= 200; i++) {
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行了任务" + i + "~");
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                //执行业务逻辑
                for(int i = 201; i <= 300; i++) {
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行了任务" + i + "~");
                }
            }
        });
    }
}

当任务量达到一定程度一个线程忙不过来时就会发现其他线程也来帮忙辽~


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java