美文网首页
并发——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