Java面试题:创建线程有几种方式
阅读原文时间:2021年04月20日阅读:1

面试官:

小伙子,说下Java创建线程有几种方法?

我:

一般情况下就是继承Thread类和实现Runnable接口。这两者之间的区别就是实现Runnable接口,可以避免了继承Thread类的单继承局限性。

下面是我总结的一些创建线程的方式

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;

/**
 * @author 2019年4月17日20:03:48
 * 创建线程的方式
 */
@Slf4j
public class CreateThreadMode {

    /**
     * 1、继承Thread类:继承Thread类和实现Runnable接口的最本质区别是实现接口可以实现多继承
     */
    class ThreadA extends Thread{
        @Override
        public void run() {
           log.info("继承Thread类:继承Thread类和实现Runnable接口的最本质区别是实现接口可以实现多继承");
        }
    }

    /**
     * 2、实现Runnable接口:继承Thread类和实现Runnable接口的最本质区别是实现接口可以实现多继承
     */
    class ThreadB implements Runnable{
        @Override
        public void run() {
            log.info("实现Runnable接口:继承Thread类和实现Runnable接口的最本质区别是实现接口可以实现多继承");
        }
    }


    public void test1(){
        /**
         * 3、匿名内部类
         */
        new Thread(){
            @Override
            public void run(){
                log.info("匿名内部类");
            }
        }.start();

        /**
         * 4、匿名内部类
         */
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("匿名内部类");
            }
        }).start();

        /**
         * 5、Lambda表达式创建线程
         */
        new Thread(() -> {
            log.info("Lambda表达式创建线程方式..." + Thread.currentThread().getName());
        }).start();

        /**
         * 6、Lambda表达式创建线程+设定线程的名称
         */
        new Thread(() -> {
            System.out.println("Lambda表达式创建线程方式..." + Thread.currentThread().getName());
        },"线程1").start();
    }

    public void test2(){
        /**
         * 7、线程池创建线程
         */
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(index+ " "+Thread.currentThread().getName()+" "+ DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        fixedThreadPool.shutdown();
    }

    class ThreadC implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("正在执行方法体......");
            Thread.sleep(3000);
            return "hello world";
        }
    }

    @Test
    public void test3() throws Exception{
        /**
         * 8、FutureTask方式进行
         */
        ThreadC threadC = new ThreadC();
        //FutureTask是继承Runnable,是对Runnable的封装,所以需要包装到Thread类中执行
        FutureTask<String> task = new FutureTask<>(threadC);
        //包装到Thread类中进行执行
        Thread t = new Thread(task);
        t.start();
        System.out.println("执行别的任务....");
        //获取线程执行结果
        String result = task.get();
        System.out.println("线程执行结果是:"+result);
    }



    @Test
    public void test4() throws Exception{
        /**
         * 9、CompletableFuture方式,详情参考https://www.jianshu.com/p/6bac52527ca4
         */
        CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
            long time = System.currentTimeMillis();
            System.out.println("run end ..."+time);
            return time;
        });
        long time = future.get();
        System.out.println("time = "+time);
    }


    @Test
    public void test5(){
        /**
         * 10、定时器方式
         */
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
           @Override
           public void run() {
               System.out.println("定时任务延迟0(即立刻执行),每隔1000ms执行一次"+ " "+Thread.currentThread().getName()+" "+ DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
           }
        }, 0, 1000);

    }

}