• (一)线程创建与运行


    Java并发编程之美->读书笔记

    Java 中有3种线程创建方式,

    1,分别为实现 Runnable 接口的 run 方法,

    2,继承 Thread并重写 run 方法,

    3,使用 FutureTask 方式 首先看继承Thread类方式实现。

    导包

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

    继承Thread类并重写run方法

        //继承Thread类并重写run方法
        public static class MyThread extends Thread {
            @Override
            public void run() {
                System.out.println("I am a children");
            }
        }
    
        public static void main(String[] args) {
            //创建线程
            MyThread myThread = new MyThread();
            //启动线程
            myThread.start();
        }
    

    如上代码中的MyThread类继承了Thread类,并重写了run()方法。

    在main函数里面创建了一个MyThread的实例,然后调用该实例的start方法启动了线程。

    需要注意的是,当创建完thread对象后该线程并没有被启动执行,知道调用了start方法后才真正启动了线程。

    其实调用start方法后线程并没有马上执行而是处于就绪状态,这个就绪状态是指该线程已经获取了除CPU资源外的其他资源,等待获取CPU资源后才会真正处于运行状态。

    一旦run方法执行完毕,该线程就处于终止状态。

    使用继承方式的好处是,在run()方法内获取当前线程直接使用this就可以了,无需使用Thread.currentThread()方法;

    不好的地方是java不支持多继承,如果继承了Thread类,那么就不能再继承其他类。

    另外任务与代码没有分离,当多个线程执行一样的任务时需要多份任务代码,而Runnable则没有这个限制。

    实现Runnable接口的run方法方式

        public static class RunnableTask implements Runnable{
    
            @Override
            public void run() {
                System.out.println("!222222");
            }
        }
    
        public static void main (String[] args){
            RunnableTask task = new RunnableTask();
            new Thread(task).start();
            new Thread(task).start();
        }
    

    如上面代码所示,两个线程共用一个task代码逻辑,如果需要,可以给RunnableTask添加参数进行任务区分。

    另外,RunnableTask可以继承其他类。但是上面介绍的两种方式都有一个缺点,就是任务没有返回值。

    使用FutureTask的方式

     //创建任务类,类似Runnable
        public static class CallerTask implements Callable<String> {
    
            @Override
            public String call() throws Exception {
                return "hello";
            }
        }
    
        public static void main(String[] args) throws InterruptedException{
            //创建异步任务
            Future<String> futureTask = new FutureTask<>(new CallerTask());
            //启动线程
            new Thread((Runnable) futureTask).start();
            try {
                String result = futureTask.get();
                System.out.println(result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    

    如上代码中的CallerTask类实现了Callable接口的call()方法。

    在main函数内首先创建了一个FutrueTask对象(构造函数为CallerTask的实例),然后使用创建的FutrueTask对象作为任务创建了一个线程并且启动它,

    最后通过futureTask.get()等待任务执行完毕并返回结果

    小结

    使用继承方式的好处是方便传参,你可以在子类里面添加成员变量,通过set方法设置参数或者通过构造函数进行传递,

    而如果使用Runnable方式,则只能使用主线程里面被声明为final的变量。

    不好的地方是java不支持多继承,如果继承了Thread类,那么子类不能再继承其他类,

    而Runnable则没有这个限制。前两种方式都没办法拿到任务的返回结果,但是Futuretask方式可以.

      

  • 相关阅读:
    Hadoop学习之路(十四)MapReduce的核心运行机制
    Hadoop学习之路(十三)MapReduce的初识
    Hadoop学习之路(十二)分布式集群中HDFS系统的各种角色
    Hadoop学习之路(十一)HDFS的读写详解
    Hadoop学习之路(十)HDFS API的使用
    Hadoop学习之路(九)HDFS深入理解
    Hadoop学习之路(八)在eclispe上搭建Hadoop开发环境
    Guava的使用
    如何用纯 CSS 创作一个过山车 loader
    如何用纯 CSS 创作一组昂首阔步的圆点
  • 原文地址:https://www.cnblogs.com/lvchengda/p/13387100.html
Copyright © 2020-2023  润新知