Java创建多线程的四种方式

Java创建多线程的四种方式


一、继承Thread类创建线程

/**
 * @author Fox
 * @date 2021/12/02 15:17
 */
public class Thread_1 extends Thread {
    public void run(){
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread()+"序号为"+i);
        }
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread_1();
        Thread thread2 = new Thread_1();
        Thread thread3 = new Thread_1();
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

结果如下图
在这里插入图片描述
注意:
继承Thread方式创建线程本质上还是通过实现Runnable接口来完成的
Thread类源码
👇
在这里插入图片描述

二、实现Runable接口创建线程

/**
 * @author Fox
 * @date 2021/12/02 15:30
 */
public class Thread_2 {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 3; j++) {
                        System.out.println(Thread.currentThread()+"该线程循环的次数为:"+j);
                    }
                }
            }).start();
        }
    }
}

结果如下图:
在这里插入图片描述

三、通过Callable接口创建线程

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

/**
 * @author Fox
 * @date 2021/12/02 16:06
 */
public class Thread_3 {
    private static int socunt = 20;
    public static void main(String[] args) {
        FutureTask ft = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                for (int i = 1; i <= 20 ; i++) {
                    socunt--;
                    System.out.println("当前卖出1,还剩余"+ socunt);
                }
                return "sale out";
            }
        });
        new Thread(ft).start();
        try {
            System.out.println(ft.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果如下图:
在这里插入图片描述
通过Callable接口创建与通过Runnable接口创建线程的区别:

  • 通过Callable实现可以抛出异常,而Runnable实现不会抛出异常.
  • 通过Callable实现具有返回值,而Runnable实现没有返回值.
  • 通过Callable实现调用的方法是call(),而Runnable实现调用的方法是run().

FutureTask是Runnable接口的实现类,根据对Java多态的理解,父类或接口的引用指向子类或实现类的对象。可知传入一个FutureTask对象就相当于传入了一个Runnable接口的具体实现。

四、通过线程池创建线程

说明:
根据阿里Java开发手册可得知线程资源必须通过线程池提供,不允许在应用中自行显示创建线程
原因是线程池的好处在于减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者"过度切换"问题。

1、Executors.newFixedThreadPool(int)

/**
 * @author Fox
 * @date 2021/12/02 18:13
 */
public class newFixedThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 7; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 3; j++) {
                        System.out.println("线程池"+Thread.currentThread().getName()+"执行的第"+j+"次");
                    }
                }
            },i);
        }
        executorService.shutdown();
    }
}


线程池pool-1-thread-3执行的第0次
线程池pool-1-thread-4执行的第0次
线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-2执行的第0次
线程池pool-1-thread-1执行的第2次
线程池pool-1-thread-4执行的第1次
线程池pool-1-thread-3执行的第1次
线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-4执行的第2次
线程池pool-1-thread-5执行的第0次
线程池pool-1-thread-5执行的第1次
线程池pool-1-thread-5执行的第2次
线程池pool-1-thread-2执行的第1次
线程池pool-1-thread-4执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-3执行的第2次
线程池pool-1-thread-1执行的第2次
线程池pool-1-thread-4执行的第1次
线程池pool-1-thread-4执行的第2次
线程池pool-1-thread-2执行的第2

2、Executors.newSingleThreadPool(int)

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

/**
 * @author Fox
 * @date 2021/12/02 18:21
 */
public class newSingleThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 3; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 3; j++) {
                        System.out.println("线程池"+Thread.currentThread().getName()+"执行的第"+j+"次");
                    }
                }
            },i);
        }
        executorService.shutdown();

    }
}


线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-1执行的第2次
线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-1执行的第2次
线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-1执行的第2

3、Executors.newCachedThreadPool(int)

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

/**
 * @author Fox
 * @date 2021/12/02 18:26
 */
public class newCachedThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 3; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 3; j++) {
                        System.out.println("线程池"+Thread.currentThread().getName()+"执行的第"+j+"次");
                    }
                }
            },i);
        }
        executorService.shutdown();
    }
}



线程池pool-1-thread-3执行的第0次
线程池pool-1-thread-3执行的第1次
线程池pool-1-thread-3执行的第2次
线程池pool-1-thread-2执行的第0次
线程池pool-1-thread-1执行的第0次
线程池pool-1-thread-1执行的第1次
线程池pool-1-thread-1执行的第2次
线程池pool-1-thread-2执行的第1次
线程池pool-1-thread-2执行的第2

三种方式底层都是new ThreadPoolExecutor();

4、ThreadPoolExecutor自定义线程池

import java.util.concurrent.*;

/**
 * @author Fox
 * @date 2021/12/02 18:30
 */
public class ThreadPoolByMyself {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程池数量
                5,//最大线程池
                3L,//空闲线程的存活时间
                TimeUnit.SECONDS,//空闲线程存活时间单位
                new ArrayBlockingQueue<>(3)//阻塞队列个数
        );
        try{
            for (int i = 0; i < 8; i++) {
                threadPoolExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName()+"  处理业务");
                    }
                });
            }
        }finally {
            threadPoolExecutor.shutdown();
        }
    }
}



pool-1-thread-1  处理业务
pool-1-thread-4  处理业务
pool-1-thread-5  处理业务
pool-1-thread-3  处理业务
pool-1-thread-1  处理业务
pool-1-thread-2  处理业务
pool-1-thread-5  处理业务
pool-1-thread-4  处理业务

注意
一般使用自定义线程池来满足业务需求
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值