美文网首页
java创建线程的方法

java创建线程的方法

作者: 樱花舞 | 来源:发表于2019-09-27 10:31 被阅读0次

java创建线程有三种方式,继承Thread类,实现Runnable接口,实现Callable接口;但Callable接口与FutureTask配合使用,而FutureTask也是实现Runnable接口,所以也也可以说两种方式。

创建线程

继承Thread类

继承Thread类重写run()方法,不过一般推荐通过实现Runnable来创建线程,因为只能继承一个类,如果想要继承其他类拓展,继承Thread就不是很友好。

public class ThreadOne extends Thread {
    @Override
    public void run() {
        System.out.println("thread one");
    }
}

调用也很简单,只要执行start()方法即可,但如果是执行run()方法,那只是执行普通方法,并不是创建线程执行的。

ThreadOne threadOne = new ThreadOne();
threadOne.start();

实现Runnable接口

public class ThreadTwo implements Runnable {
    @Override
    public void run() {
        System.out.println("thread two");
    }
}

创建Runnable线程需要把类传入Thread实例中。

ThreadTwo threadTwo = new ThreadTwo();
Thread thread = new Thread(threadTwo);
thread.start();

实现Callable接口

这种方式创建线程是可以获得子线程返回结果的,是Runnable的加强版。

public class ThreadThree implements Callable<Long> {
    @Override
    public Long call() throws Exception {
        System.out.println("thread three");
        return 23L;
    }
}

这种方式也需要把实例传入Thread中才能创建线程,执行完之后可以通过FutureTask的get()获取返回结果。

ThreadThree threadThree = new ThreadThree();
FutureTask<Long> future = new FutureTask<>(threadThree);
new Thread(future).start();
//输出返回结果
System.out.println(future.get());

创建线程池

如果在程序中随意创建线程,需要就创建,这是一种不好的方式,不容易管理,代码混乱,同时可能造成一些线程问题。需要用到多线程就必须使用线程池,这是一个好的开发习惯。
线程池主要是实现ExecutorService,而jdk已经实现,可以通过Executors类创建或者new ThreadPoolExecutor来创建,而Executors实际也是通过new ThreadPoolExecutor创建,不过不推荐使用Executors方式创建,至于原因网上很多文章说明,阿里巴巴开发规范也不推荐使用这种方式。
ExecutorService 的submit把要创建的线程提到线程池,由线程池执行,同时可以获取子线程的返回结果。

public class Test {
    private static ExecutorService executorService = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
            Runtime.getRuntime().availableProcessors() * 2, 0L,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(512),
            new ThreadPoolExecutor.DiscardPolicy());
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadOne threadOne = new ThreadOne();

        ThreadTwo threadTwo = new ThreadTwo();

        ThreadThree threadThree = new ThreadThree();

        Future<?> a = executorService.submit(threadOne);
        Future<?> b = executorService.submit(threadTwo);
        Future<?> c = executorService.submit(threadThree);
        //输出结果
        System.out.println(a.get());
        System.out.println(b.get());
        System.out.println(c.get());
    }
}

在实际中,经常有这样的场景,大量的数据然后分批次建立子线程来执行,获取子线程执行结果然后统一返回,若线程池以下面的方式操作 就是一种错误方式。在循环中,在线程池中执行子线程,然后把结果保存到集合中,然而这种方式没有多线程效果,在循环中等待子线程执行完之后获取到结果,然后再下一次循环再执行一个子线程。

    public static void errorMethod() throws ExecutionException, InterruptedException {
        List<Long> result = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ThreadThree threadThree = new ThreadThree();
            //阻塞等待结果,实际相当于等子线程执行完之后然后再创建子线程,然后再执行,没有多线程的效果
            Future<Long> future = executorService.submit(threadThree);
            result.add(future.get());
        }
    }

正确的姿势应该是这样的:

    public static void test() throws InterruptedException, ExecutionException {
        List<Callable<Long>> callables = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ThreadThree threadThree = new ThreadThree();
            callables.add(threadThree);
        }
        List<Future<Long>> futures = executorService.invokeAll(callables, 10, TimeUnit.SECONDS);
        List<Long> result = new ArrayList<>();
        for (Future<Long> future : futures) {
            result.add(future.get());
        }
    }

先把要执行的子线程保存集合,然后调用用invokeAll方法全部执行,设置超时时间,若在超时时间内没有执行完所有子线程抛出异常。

相关文章

  • 线程池的使用

    Java线程池 前言 平时使用Java线程时,习惯于直接new Thread来创建一个线程,这种创建线程的方法随手...

  • Java并发编程基础教程—并发基础(二)

    Java线程 3.1线程的创建和运行 方法1 方法2 Java8 使用lambda表达式Runnable r = ...

  • 创建线程的3种方法

    转载 Java创建线程的3中方法 继承Thread类创建线程类 通过Runnable接口创建线程类 通过Calla...

  • 3、并发编程-Java线程

    并发编程 Java线程 创建和运行线程 查看线程 线程API 线程状态 创建和运行线程 方法一,直接使用new T...

  • java多线程

    java多线程 [TOC] 创建线程 直接调用Thread类或Runnable类的run方法并不会 创建线程,只会...

  • java 创建线程的方法

    java 创建线程的方法 Java通过Executors提供四种线程池,分别为: newCachedThreadP...

  • 线程的基本使用

    线程的创建 java创建线程有两种方法​​ 创建Thread的子类 实现Runnable接口 Thread和Run...

  • 线程基础

    ** java中创建线程的方法** 继承自java.lang.thread类,并重写run方法(线程运行时要做的事...

  • Java学习总结——多线程编程

    Java多线程编程 一、创建线程的方法一: 继承:extends Thread 重写run()方法 举个栗子?: ...

  • C++主线程调用Java方法

    1. C++ 全局调用Java方法 1.1 C++主线程调用Java方法 在 Android C++多线程-创建子...

网友评论

      本文标题:java创建线程的方法

      本文链接:https://www.haomeiwen.com/subject/itnhuctx.html