2023.10.7 Java 创建线程的七种方法

目录

继承 Tread 类,重写 run 方法

实现 Runnable 接口 

使用匿名内部类,继承 Thread 类

使用匿名内部类,实现 Runable 接口

使用 Lambda 表达式

使用线程池创建线程

实现 Callable 接口 


继承 Tread 类,重写 run 方法

  • 自定义一个 MyThread类,用来继承 Thread 类,重写 run 方法,最后在 main 方法中new 出 MyThread 实例,并调用该实例继承自父类 Thread 类的 start 方法,从而创建一个新线程
//先创建一个类 让该类继承 Thread 父类
class MyThread extends Thread {
//    重写 run 方法
    @Override
    public void run() {
        System.out.println("在 run方法中 自定义线程的工作内容");
    }
}

public class ThreadDemo1 {
    public static void main(String[] args) {
//        创建实例t
        Thread t = new MyThread();
//        启动并创建新线程
        t.start();
//        run 方法仅执行 run方法中的代码,并不会创建一个新线程
//        t.run();
    }
}

注意:

  • 创建实例并不会直接创建一个线程,而是调用到 start 方法才会创建一个新线程
  • 一个进程至少含有一个线程,JVM 默认创建线程为 主线程(main),主线程(main)与 MyThread 创建出来的新线程为并发执行,同时执行,各执行各的

实现 Runnable 接口 

  • 自定义一个 MyRunnable 类,用来实现 Runnable 接口,重写 run 方法,最后在 main 方法中new 出 Thread 实例,并调用该实例的 start 方法,从而创建一个新线程
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("在 run方法中 自定义线程的工作内容");
    }
}

public class ThreadDemo2 {
    public static void main(String[] args) {
//        这只是描述了个任务
        Runnable runnable = new MyRunnable();
//        把任务交给线程来执行
        Thread t = new Thread(runnable);
        t.start();
    }
}

注意:

  • 该方式能将 线程 和 线程要干的活 之间分离开,从而达到 解耦合 的效果
  • 如果要改动代码,不用使用多线程,转而使用多进程、线程池等,此时代码的改动较小

使用匿名内部类,继承 Thread 类

  • 直接创建 Thread 子类,同时实例化出一个对象,重写 run 方法,并调用该实例的 start 方法,从而创建一个新线程
public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                System.out.println("在 run方法中 自定义线程的工作内容");
            }
        };
        t.start();
    }
}

注意:

使用匿名内部类,实现 Runable 接口

  • 使用匿名内部类,实现 Runnable 接口作为 Thead 构造方法的参数,最后调用实例的 start 方法,从而创建一个新线程
public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("在 run方法中 自定义线程的工作内容");
            }
        });
        t.start();
    }
}

使用 Lambda 表达式

  • lambda 本质为以一个匿名函数,()表示函数的形参,-> 为特殊语法,{ } 表示函数体,以上构成一个 lambda 表达式
public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("自定义线程的工作内容");
        });
        t.start();
    }
}

使用线程池创建线程

  • ThreadPoolExecutor(线程池)的构造方法写起来很麻烦,但是标准库提供了一系列工程方法来简化其使用
  • 工厂模式:将产品实例的权利移交给工厂,程序员不再通过 new 来创建所需对象,而是通过工厂获取所需产品,降低了产品使用者与使用者之间的 耦合关系
  • 使用线程池不需显示的 new,而是通过 Executors 这个静态方法 new CaChedThreadPool 来完成
  • 当然使用 submit 方法,将任务提交到线程池中,线程池中会有线程来完成这些任务
package Thread;

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

public class ThreadDemo6 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();

        pool.submit( new Runnable() {
            @Override
            public void run() {
                System.out.println("在 run方法中 自定义线程的工作内容");
            }
        });
    }
}

 实现 Callable 接口 

  • 类似于 Runnable 一样
  • Runnable 用来描述一个任务,描述的任务是 没有返回值
  • Callable 也是用来描述一个任务,描述的任务是 有返回值
  • 如果需要使用一个线程单独的计算出某个结果来,此时使用 Callable 是比较合适的

实例理解

  • 创建线程计算 1 + 2 + 3 + ... + 1000,并返回结果
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo30 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        使用 Callable 来计算 1 + 2 + 3 + ... + 1000
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
//            相当于 Runnable 的 run 方法,run 方法返回值是 void
//            此处的 call 方法返回值是 泛型参数
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 0; i <= 1000; i++) {
                    sum += i;
                }
                return sum;
            }
        };
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t = new Thread(futureTask);
        t.start();

//        get 方法就是获取结果
//        get 会发生阻塞,直到 callable 执行完毕,get 才阻塞完成,才获取到结果
        Integer result = futureTask.get();
        System.out.println(result);
    }
}
  • 上述代码中,callable 不能直接传入到 Thread 的构造方法里,需要套上一层其他的辅助类 FutureTask
  • Thread 类的构造方法接受的是一个实现了 Runnable 接口的对象,而不是 Callable 接口的对象
  • 为了能在 Thread 中执行 Callable 任务,需要使用一个中介类来桥接它们之间的差异,即 FutureTask 类
  • FutureTask 实现了 Runnable 接口,同时也实现了 Future 接口,因此可以将 Callable 任务封装起来,使其具备了 Runnable 的特性,可以在后台线程中执行
  • 它还提供了获取计算结果的方法,如 get 方法

运行结果

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茂大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值