Java创建并执行线程的四种方法

小灰灰 2023-10-02 10:41 15阅读 0赞

Java创建并执行线程的四种方法

java里面创建线程有四种方式:
无返回:

  1. 实现Runnable接口,重写run();
  2. 继承Thread类,重写run();
    有返回:
  3. 实现Callable接口,重写call(),利用FutureTask包装Callable,并作为task传入Thread构造函数;
  4. 利用线程池;

下面来看看具体的创建方式:

  1. 继承Thread类,重写run();
    创建:创建线程只需要继承Thread类,然后在run方法里写下线程要实现的任务即可;
    在这里插入图片描述
    调用:通过调用start方法来启动线程而不能直接调用run方法。
    在这里插入图片描述

① Thread类本质上是实现了Runnable接口,Thread对象代表一个线程的实例。
② Runnable接口只有一个抽象的run()方法。
③ 启动线程的唯一方法就是通过Thread类的start()实例方法。
④ start()方法是一个native方法,它将启动一个新线程,并执行run()方法。
⑤ 自定义类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。

  1. 创建任务,实现Runnable接口,重写run()。(受欢迎)
    因为Java只能单继承,继承了Thread类就不能再继承别的类了所以实现继承更推崇的是让线程类实现Runnable接口。
    在这里插入图片描述
    将Runnbale作为参数传入Thread的构造函数,创建Thread.
    在这里插入图片描述
  2. Callable接口只包含抽象方法V call()。
    在这里插入图片描述
    利用Callable接口创建并启动新线程的步骤:
    ① 定义MyClass实现Callable接口;Class MyClass implements Callable
    ② 重写call(),将执行的代码写入;
    ③ 创建FutureTask的对象;FutureTask中定义了run(),run()内部调用了call(),并保存了call()的返回值;FutureTask futuretask = new FutureTask(newMyClass());
    ④ 创建Thread的对象;Thread thread = new Thread(futuretask);//传入参数Runnable接口
    ⑤ 启动线程;thread.start();[图片]
    ⑥ 可通过FutureTask类的get()方法获得线程执行结束后的返回值,即call的返回值。futuretask.get();

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

    public class MyThread {

  1. public static void main(String[] args) throws InterruptedException {
  2. FutureTask<Integer> task = new FutureTask<Integer>(new CallableImpl());
  3. Thread thread = new Thread(task);
  4. thread.start();
  5. try {
  6. System.out.println("task.get() returns " + task.get());
  7. } catch (ExecutionException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }
  12. class CallableImpl implements Callable<Integer> {
  13. private static Integer value = 0;
  14. @Override
  15. public Integer call() throws Exception {
  16. System.out.println("执行call方法之前 value = " + value);
  17. value = value.intValue() + 1;
  18. System.out.println("执行call方法之后 value = " + value);
  19. return value;
  20. }
  21. }

运行结果:
执行call方法之前 value = 0
执行call方法之后 value = 1
task.get() returns 1

  1. 通过线程池来创建线程
    ① new ThreadPoolExecutor(…);
    ② 创建任务Task implements Callable,重写run()方法;
    ③ 通过线程池的execute()或submit()将任务command传入线程池;
    ④ 获取返回值:

  2. 实现Callable接口,重写call()方法
    class CallableImpl implements Callable

  3. 定义线程池
    ThreadPoolExecutor executor
  4. 利用submit()方法提交任务
    Future<?> future = executor.submit(new CallableImpl());
  5. 利用FutureTask类get()方法获取返回值
    res = task.get();
    这里future申明为Future对象,但是它是由FutureTask实现的,也可以直接申明为FutureTask future:

    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;

    public class MyThreadPool {

    1. public static void main(String[] args) throws InterruptedException, ExecutionException {
  1. ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
  2. new ArrayBlockingQueue<Runnable>(20));
  3. Future task;
  4. for (int i = 0; i < 5; i++) {
  5. task = executor.submit(new CallableImpl());
  6. System.out.println("线程返回结果:" + task.get());
  7. }
  8. executor.shutdown();
  9. }
  10. }
  11. class RunnableImpl implements Runnable {
  12. @Override
  13. public void run() {
  14. // TODO Auto-generated method stub
  15. System.out.println("hhh");
  16. System.out.println(Thread.currentThread().getName());
  17. }
  18. }

运行结果:
执行call方法之前 value = 0
执行call方法之后 value = 1
线程返回结果:1
执行call方法之前 value = 1
执行call方法之后 value = 2
线程返回结果:2
执行call方法之前 value = 2
执行call方法之后 value = 3
线程返回结果:3
执行call方法之前 value = 3
执行call方法之后 value = 4
线程返回结果:4
执行call方法之前 value = 4
执行call方法之后 value = 5
线程返回结果:5

总结:
线程的创建有四种方式:主要分为有返回和无返回,具体根据使用场景来选择。

  1. 如果不需要返回且线程数量小,则建议采用实现Runnable接口,重写run()的方式;
  2. 如果需要返回且线程数量小,则建议采用实现Callable接口,重写call(),利用FutureTask包装成一个Runnable,再作为参数传入Thread的构造方法的方式创建线程;
  3. 如果线程数量较多,则建议采用线程池方式创建:execute提交任务实现无返回操作,submit提交任务实现有返回操作。

补充:FutureTask
JDK1.8中FutureTask实现了RunnableFuture,而RunnableFuture顾名思义就是Runnable接口和Future接口的结合体。因此,FutureTask对象可以作为Runnable对象来用,比如

  1. Thread thread = new Thread(new FutureTask<V>());

也可以作为Future来用。这就是Java的有魅力的地方。。。

  1. public class FutureTask<V> implements RunnableFuture<V>
  2. public interface RunnableFuture<V> extends Runnable, Future<V> {
  3. void run();
  4. }

发表评论

表情:
评论列表 (有 0 条评论,15人围观)

还没有评论,来说两句吧...

相关阅读