美文网首页
并发——Java 中创建线程的3种方法

并发——Java 中创建线程的3种方法

作者: 四喜汤圆 | 来源:发表于2019-07-11 19:23 被阅读0次

一、3种方法

1.继承 Thread 类

(1)创建 Thread 类的子类
重写run(),该方法就是线程的执行体

(2)创建 Thread 继承类的实例
即创建了线程对象

(3)调用线程对象的start()开启线程

public class Thread1 extends Thread {
    @Override
    public void run() {
        super.run();
        // 线程执行体
    }

    public static void main(String[] args) {
        Thread t = new Thread();
        t.start();
    }
}

2. 实现 Runnable 接口

(1)创建 Runnable 接口的实现类
重写run()作为线程执行体

(2)创建 Runnable 实现类的实例
将该实例作为 Thread 的 target 传入创建 Thread 对象,该 Thread 类的实例是线程对象

(3)调用线程对象的start()开启线程

public class Thread2 {

    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 线程执行体
        }
    }

    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    }

}

3. Callable

(1)Callback 和 FutureTask 相结合

  • 创建Callable接口的实现类
    重写call()方法,为线程执行体。

  • 用 FutureTask 包装 Callable 实现类的实例
    FutureTask实现了Runnable接口。创建 Callable 实现类的实例,并用 FutureTask 包装,该FutureTask对象封装了该Callable对象的call()方法的返回值。

  • 将 FutureTask 实例作为 Thread 的 target 创建 Thread 对象
    该 Thread 对象为线程对象,通过start()启动线程。

  • 用 FutureTask 对象的get()方法来获得子线程执行结束后的返回值,调用get()方法会阻塞线程。

public class CallableTest {
    /**
     * Callable和FutureTask
     * FutureTask::get()的阻塞性
     */
    public static void main(String[] args) {
        MyCallable myCallable = new MyCallable();
        FutureTask < Integer > futureTask = new FutureTask(myCallable);
        Thread t = new Thread(futureTask);
        t.start();
        // 会阻塞线程
        try {
            System.out.println(futureTask.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class MyCallable implements Callable < Integer > {

        @Override
        public Integer call() throws Exception {
            return 0;
        }
    }
}

(2)Callable 和 Future 相结合
Java 并发编程

public class CallableTest {
    /**
     * Callable和Future
     * Future::get()的阻塞性
     * 在调用submit提交任务之后,主线程本来是继续运行了。但是运行到future.get()的时候就阻塞住了,一直等到任务执行完毕,拿到了返回的返回值,主线程才会继续运行。
     *
     * 这里注意一下,他的阻塞性是因为调用get()方法时,任务还没有执行完,所以会一直等到任务完成,形成了阻塞。
     *
     * 任务是在调用submit()方法时就开始执行了,如果在调用get()方法时,任务已经执行完毕,那么就不会造成阻塞。
     * @param args
     */
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        MyCallable callable = new MyCallable();
        Future < Integer > future = executorService.submit(callable);
        try {
            Integer res = future.get();
            System.out.println(res);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static class MyCallable implements Callable < Integer > {

        @Override
        public Integer call() throws Exception {
            return 0;
        }
    }
}

二、比较

RunnableCallable(实现接口的方式)

  • 优势
    (1)还可继承其他类;(2)在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

  • 劣势
    编程较麻烦,获取当前线程的方法Thread.getCurrentThread()

Thread

  • 优势
    编程简单;通过this获取当前线程。

  • 劣势
    不可再继承其他类。

参考文献

lrh_Java线程

相关文章

网友评论

      本文标题:并发——Java 中创建线程的3种方法

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