Java中实现多线程的方式

1、继承Thread类

通过继承Thread类,并重写run方法

public class MyThread extends Thread{

    public static void main(String[] args) {

        MyThread myThread1=new MyThread();
        MyThread myThread2=new MyThread();
        myThread1.start();
        myThread2.start();
    }

    @Override
    public void run() {
        super.run();
        System.out.println("MyThread.run()");
    }
}

2、实现Runnable接口

实现Runnable接口,并重写run方法

public class MyThread1 implements Runnable{
    public static void main(String[] args) {
        MyThread1 myThread1=new MyThread1();
        Thread thread=new Thread(myThread1);
        thread.start();
    }
    @Override
    public void run() {

        System.out.println("创建多线程--->实现Runnable接口");
    }
}

3、实现Callable接口

实现Callable接口,并重写call方法
1、Callable接口有返回值,通过FutureTask可以获取返回值
2、与Runnable接口相比,Callable接口可以抛出异常

public class Mythread2  {

    private static Integer Integer;

    public static void main(String[] args)  {

        //1.实例化一个CallableTest对象
        CallableTest callableTest=new CallableTest();
        //2.实现Callable接口,需要FutureTask实现类的支持,用于接受运算结果
        FutureTask futureTask=new FutureTask(callableTest);
        //3.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

        try {
            //4.通过get方法获取结果
            Object sum = futureTask.get();
            System.out.println("0到100偶数的总和为:"+sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }


    static class CallableTest implements Callable {

        @Override
        public Integer call() throws Exception {
            int sum=0;
            for (int i=0;i<=100;i++){
                if (i%2==0){
                    sum+=i;
                }
            }
            return sum;
        }
    }

}

4、通过线程池的方式实现多线程

java中ThreadPoolExecutor实现多线程的方法

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
参数说明
corePoolSize

核心线程数,核心线程池的大小,当一个任务提交到线程池的时候,核心线程池会创建一个核心线程来执行任务

  • 核心线程数会一直存活,即便没有任务需要执行的情况
  • 当线程数小于核心线程数时,即便有线程空闲,线程池也会创建新线程处理
  • 设置allowsCoreThreadTimeOut=true(默认false)时,核心线程会超时关闭
maximumPoolSize

最大线程数

  • 当线程数>=corePoolSize,且任务队列已满时,线程池会创建新线程来处理任务
  • 当线程数=maximumPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常
keepAliveTime

线程空闲时间

  • 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
  • 如果allowsCoreThreadTimeOut=true,则会知道线程数量=0
TimeUnit

时间单位

BlockingQueue

任务队列

  • 核心线程数达到最大时,新任务会放在队列中排队进行等待
RejectedExecutionHandler

拒绝策略,当线程池的队列已经满了的情况下。新进入的任务添加到线程池的时候就会进行处理,JDk默认有四种任务拒绝策略

  • AbortPolicy(默认): 默认的拒绝策略,会直接抛出RejectedExecutionException异常
  • DiscardPolicy: 当新任务被提交后直接被丢弃
  • DiscardOldestPolicy: 当新任务添加进线程池的时候,会放弃任务队列中的头节点,此时丢弃的是队列中存活时间最长的队列
  • CallerRunsPolicy: 该策略既不会抛弃任务,也不会抛出异常,而是将任务回推到调用者。"顾名思义,在饱和的情况下,调用者会执行该任务
  • 用户自定义拒绝策略: 实现RejectedExecutionHandler,并自己定义策略模式
线程池的执行原理
  • 工作流程图如下
    https://gitee.com/ycodingnow/blogimage/blob/master/image/20220609110249.png
posted @ 2022-06-08 10:59  龙空白白  阅读(28)  评论(0编辑  收藏  举报