面试官:小伙子,说一说Java多线程有哪些创建方式吧

第一种 继承Thread类

自定义类,继承Thread类,并重写run()方法.

class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println("第一种方式Thread " + Thread.currentThread().getName());
    }
}
public class Test {
    public static void main(String[] args) throws Exception {
        //第一种方式
        MyThread1 thread1 = new MyThread1();
        thread1.start();
        
        MyThread1 thread1 = new MyThread1();
        thread1.start();

        MyThread1 thread2 = new MyThread1();
        thread2.setName("zz");
        thread2.start();
        // 运行结果
        // 第一种方式Thread Thread-0
        // 第一种方式Thread Thread-1
        // 第一种方式Thread zz
        // 若不指定Name属性,能默认计数器0,1,2,3,4,5
    }
}

  

第二种 实现Runnable接口

自定义类,实现Runnable接口的run方法. since JDK1.0

class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println("第二种方式Runnable " + Thread.currentThread().getName());
    }
}
public class Test {
    public static void main(String[] args) throws Exception {
        //第二种方式
        Thread thread2 = new Thread(new MyThread2());
        thread2.start();
        // Lambda表达式方式->因为Runnable被注解FunctionalInterface标识表明该接口是一个函数式接口
        new Thread(() -> {
            System.out.println("第二种方式Runnable_Lambda " + Thread.currentThread().getName());
        }).start();
        // 运行结果
        // 第二种方式Runnable Thread-0
        // 第二种方式Runnable_Lambda Thread-1
    }
}

  

第三种 实现Callable接口

已知Runnable的run方法无返回值,所以引入了有返回值的Callable接口
since JDK1.5

FutureTask中构造方法如下.

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

  

FutureTask类结构图如下.

 
 

因为FutureTask类实现了Runnable接口,所以线程实现方法如下.

public class Test {
     public static void main(String[] args) throws Exception {
        //第三种方式
        FutureTask<String> thread3 = new FutureTask<>(new MyThread3());
        new Thread(thread3).start();
        System.out.println(thread3.get()); //获得回调值
        
        FutureTask<String> thread4 = new FutureTask(()->{
            System.out.println("Call");
            return "Lambda回调";
        });
        new Thread(thread4).start();
        System.out.println(thread4.get());
        // 运行结果
        // 第三种方式Callable Thread-0
        // 回调
        // Call
        // Lambda回调
    }
}
class MyThread3 implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("第三种方式Callable " + Thread.currentThread().getName());
        return "回调";
    }
}

  

第四种 线程池

交付线程池两种方式 submit或者execute方法,前者可接受Callable接口对象,有返回值,后者无返回值

public class Test {
    public static void main(String[] args) throws Exception {
        //第一种方式
        MyThread1 thread1 = new MyThread1();
        thread1.start();
        //第二种方式
        Thread thread2 = new Thread(new MyThread2());
        thread2.start();
        //第三种方式
        FutureTask<String> thread3 = new FutureTask<>(new MyThread3());
        new Thread(thread3).start();
        System.out.println(thread3.get());
        //第四种方式
        ExecutorService pool = Executors.newFixedThreadPool(5);
        Future<?> submit1 = pool.submit(new MyThread1());
        Future<?> submit2 = pool.submit(new MyThread2());
        Future<?> submit3 = pool.submit(new MyThread3());
        System.out.println(submit1.get() + " " + submit2.get() + "  " + submit3.get());
        pool.shutdown();
        // 运行结果
        // 第一种方式Thread Thread-0
        // 第二种方式Runnable Thread-1
        // 第三种方式Callable Thread-2
        // 回调
        // 第一种方式Thread pool-1-thread-1
        // 第二种方式Runnable pool-1-thread-2
        // 第三种方式Callable pool-1-thread-3
        // null null  回调
    }

}

  

特点

无论何种方式,都要使用Thread类中start方法开始多线程.
Runnable接口和Callable接口区别,后者可返回参数,参数类型Object.
线程池避免了线程频繁使用的创建和释放操作.

看完有什么不懂的欢迎在下面留言评论!

 

posted @ 2020-05-17 19:52  前程有光  阅读(167)  评论(0编辑  收藏  举报