线程创建的8种方式,Callable runnable submit和execute方法 futureTask

java中创建多线程是基于下面四种组件:Callable runnable ExecutorService的submit和execute方法  futureTask,这里简单介绍这些组件和创建线程的8种方式

ExecutorService的execute和submit方法区别与联系

submit---带返回值
<T> Future<T>    submit(Callable<T> task)
提交值返回任务以执行,并返回代表任务待处理结果的Future。
Future<?>    submit(Runnable task)
提交一个可运行的任务执行,并固定返回null
<T> Future<T>    submit(Runnable task, T result)
提交一个可运行的任务执行,并返回一个表示该任务的未来。

execute--不带返回值
void execute(Runnable command)
在将来的某个时间执行给定的命令。 该命令可以在一个新线程,一个合并的线程中或在调用线程中执行,由Executor实现。

FutureTask

FutureTask实现了Runnable接口和Future接口

FutureTask(Callable<V> callable)
创建一个 FutureTask ,它将在运行时执行给定的 Callable 。
FutureTask(Runnable runnable, V result)
创建一个 FutureTask ,将在运行时执行给定的 Runnable ,并安排 get将在成功完成后返回给定的结果。

Callable接口和Runnable区别

Callable接口:
public interface Callable<V> {
    V call() throws Exception;
}
Runnable接口:
public interface Runnable {
    public abstract void run();
}

相同点:
两者都是接口;(废话)
两者都可用来编写多线程程序;
两者都需要调用Thread.start()启动线程;
 
不同点:
两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

创建线程的8种方法

没有返回值方式3种:
实现runnable接口--1种
继承Thread--1种
线程池:ExecutorService.execute(runnable)

有返回值方式5种
FutureTask实现的方式--2种
    new Thread(new FutureTask(Runnable,result)).start()--固定返回值方式
    new Thread(new FutureTask(callable)).start()--非固定返回值方式

线程池实现三种
ExecutorService.submit(runnable,result)----固定返回值方式
ExecutorService.submit(runnable)---固定返回值方式,且返回值为null
ExecutorService.submit(callable)---非固定返回值方式

说明:,其实submit底层也会用到execute,所以如果提交的任务不需要一个结果的话直接用execute()会提升很多性能。结论二:就是相当于说如果你传的任务是需要结果的,那你就使用你的类去继承Callable接口,然后告诉submit方法就行了,如果你只需要一个特定的结果,就把那个特定的结果告诉submit方法然后把你想要的特定结果也告诉他,它只是帮你完成以前使用Future模式的时候你自己需要做的那些步骤而已,如果你不需要一个结果,那么就老老实实使用execute,如果你需要的是一个空结果,那么submit(yourRunnable)与submit(yourRunnable,null)是等价的!

按返回值类型划分可以分为返回值为null(runnable1种),返回值固定(runnable2种),和返回值不固定(callable2种)

如果需要有返回值的多线程,要么借助futureTask,要么用submit的返回future方式,这样才有返回值
callable实现多线程,返回值是不定的
Runnable的有返回值一定是确定的

下面是创建线程的一些实例。

1实现Runnable接口

定义线程类实现Runnable接口,重写run()方法,线程类实例化,实例化线程类引用线程类的实例化,线程类调用start()方法(推荐使用实现接口、灵活)

class Runner inplements Runnable{

  public void run(){

  }

}

Runner runner=new Runner();

Thread thread=new Thread(runner);

thread.start();

2 继承Thread,重写run方法

   定义一个Thread的子类,重写run()方法,子类实例化,然后调用start()方法

class Mythread extends thread{

  public void run(){

  }

}

Mythread mythread=new Mythread();

mythread.start();

 

3FutureTask+Callable

 /**

     * 通过new Thread(new FutureTask(callable))开启线程

     */

    private void callableFutureTaskThread() {

        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {

            @Override

            public String call() throws Exception {

                System.out.println("通过new Thread(new FutureTask(callable))开启线程");

                return "finish 通过new Thread(new FutureTask(callable))开启线程";

            }

        });

        new Thread(futureTask).start();

        try {

            System.out.println(futureTask.get());

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (ExecutionException e) {

            e.printStackTrace();

        }

    }

   

4ExecutorService+FutureTask+Callable

FutureTask的经典使用方法,利用FutureTask和ExecutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,在异步获取子线程的执行结果。

public class Caller implements Callable<Integer>{



    @Override

    public Integer call() throws Exception {

        int result = 0;

        for(int i=0;i<10;i++){

            result += i;

        }

        Thread.sleep(3000l);

        return result;

    }



    public static void main(String[] args) {

        ArrayList<FutureTask<Integer>> arrayList = new ArrayList<FutureTask<Integer>>();

        ExecutorService threadPool = Executors.newCachedThreadPool();

        for(int i=0 ;i<5;i++){

            FutureTask<Integer> task = new FutureTask<Integer>(new Caller());//callable需要用futuretask封装,然后调用线程池submit方法返回future

            arrayList.add(task);

            threadPool.execute(task);

            threadPool.submit(task);

        }

        threadPool.shutdown();

        System.out.println("main running ------");

        while(!threadPool.isTerminated()){

           

        }

        System.out.println("main running after all task down ------");

       

        int result=0;

        for(FutureTask<Integer> task : arrayList){

            try {

                result += task.get();

            } catch (InterruptedException e) {

                e.printStackTrace();

            } catch (ExecutionException e) {

                e.printStackTrace();

            }

        }

        System.out.println("result:"+result);

    }

}

5 ExecutorService.submit+Callable

/**

     * 通过 executorService.submit(callable)并且return一个Future开启线程

     */

    private void executorServiceCallableFuture() {

        ExecutorService executorService = Executors.newFixedThreadPool(5);//创建一个可重用固定线程数的线程池;

        Future<String> future = executorService.submit(new Callable<String>() {

            @Override

            public String call() throws Exception {

                System.out.println("通过 executorService.submit(callable)并且return一个Future开启线程");

                return "finish 通过 executorService.submit(callable)并且return一个Future开启线程";

            }

        });

        try {

            System.out.println(future.get());

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (ExecutionException e) {

            e.printStackTrace();

        }

    }

6ExecutorService.submit+Runnable

/**

     * 通过 executorService.submit(runnable,T)并且return一个Future开启线程

     */

    private void executorServiceRunnableFuture() {

        ExecutorService executorService = Executors.newFixedThreadPool(5);//创建一个可重用固定线程数的线程池;

        Future<String> future = executorService.submit(new Runnable() {

            @Override

            public void run() {

                System.out.println("通过 executorService.submit(runnable,T)并且return一个Future开启线程");

            }

        },"finish 通过 executorService.submit(runnable,T)并且return一个Future开启线程");

        try {

            System.out.println(future.get());

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (ExecutionException e) {

            e.printStackTrace();

        }

    }

直接run() 和 通过线程调用start()区别?

调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法,无法达到启动多线程的目的,相当于主线程线性执行 Thread 对象的 run() 方法。
一个线程对线的 start() 方法只能调用一次,多次调用会抛出 java.lang.IllegalThreadStateException 异常;run() 方法没有限制。
 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值