• Java多线程的不同实现方式


    5种创建方式:

    • 继承Thread类
    • 实现Runnable接口
    • 使用匿名内部类方式
    • 实现Callable接口
    • 使用线程池的方式

    1. 继承Thread类
    Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。

    public class multiThreading1 extends Thread{
        public void run(){
            System.out.println("111");
        }
        public static void main(String[] args) {
            multiThreading1 m1 = new multiThreading1();
            m1.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 实现Runnable接口
    实现Runnable接口的多线程要启动需要先实例化一个Thread,然后传入自己的实现Runnable接口的类的实例。
    事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run()。

    public class multiThreading2 implements Runnable{
        //重写run方法
        @Override
        public void run() {
            System.out.println("22222");
        }
        public static void main(String[] args) {
            //实例化一个Thread,然后传入multiThreading2类的实例
            Thread thread = new Thread(new multiThreading2());
            thread.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3. 使用匿名内部类方式

    public class MyThread {
        public static void main(String[] args) {
            //第一种相当于继承Thread类,通过子类的方式来实现
            new Thread("匿名内部类1"){
                @Override
                public void run(){
                    System.out.println(Thread.currentThread().getName()+"33");
                }
            }.start();
            //第二种将实现Runnable接口的类作为参数传进去
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"44");
                }
            },"匿名内部类2").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4. 实现Callable接口
    实现Callable接口是有返回值的,实现call接口,相比于Runnable接口是没有返回值的,这是两者的区别。使用该方法的一些步骤:
    ①创建Callable接口的实现类 ,并实现Call方法
    ②创建Callable实现类的实例对象
    ③创建FutureTask类的实例对象,通过FutureTask类包装Callable对象,该FutureTask的实例对象封装了Callable对象的Call方法的返回值
    ④创建Thread对象,使用FutureTask对象作为Thread对象的target创建并启动线程
    ⑤调用FutureTask对象的get()来获取子线程的返回值

    public class multiThreading3 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("Callable正在计算...");
            Thread.sleep(3000);
            return 1;
        }
        public static void main(String[] args) throws Exception {
            //创建Callable实现类的实例
            multiThreading3 threading3 = new multiThreading3();
            //使用FutureTask类包装Callable对象
            FutureTask<Integer> futureTask = new FutureTask<>(threading3);
            //创建Thread对象
            Thread thread = new Thread(futureTask);
            thread.start();
            //调用FutureTask对象的get()来获取子线程的返回值
            Integer result = futureTask.get();
            System.out.println("结果为:" + result);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    5. 使用线程池的方式
    从java5开始,提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。

    public class multiThreading4 {
    
        //定义线程池数量
        private static int POOL_NUM = 10;
    
        public static void main(String[] args) {
            //创建线程池
            ExecutorService executorService = Executors.newFixedThreadPool(5);
            for (int i = 0; i < POOL_NUM; i++) {
                //执行线程
                executorService.execute(new RunnableThread());
            }
            //关闭线程池
            executorService.shutdown();
        }
    }
    class RunnableThread implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    Xilinx ZYNQ 7000学习笔记五(Xilinx SDK 烧写镜像文件)
    如何向PDB文件添加双键
    图像的频域--学习笔记
    华纳云:openstack vm ip无故丢失的原因是什么
    基于Labview的噪声采集分析系
    xml schema中的all元素
    Java异常你了解吗?
    SpringBoot 配置 Redis 连接池
    第八章 字符输入输出和输入验证
    11-20==c++知识点
  • 原文地址:https://blog.csdn.net/yangen2018/article/details/126543030