📖JAVA中创建线程的三种方式的使用与区别

发布: 2016-04-29
热度: 53
趋势: 53
权重: 0
🎯

JAVA中通过继承Thread类、实现Runnable接口以及实现Callable接口配合Future接口实现创建多线程,三种方式各有优缺点,而第三种则具备更多的增强能力

创建线程

需要注意的是,本节没有讨论线程池的应用,仅针对单个线程的创建方式。

继承 Thread 类

/**
 * 通过继承Thread类实现多线程
 */
public class MyThread extends Thread {
    public MyThread() {
        System.out.println("构造!调用线程名:"+Thread.currentThread().getName());
    }

    @Override
    public void run() {
        System.out.println("线程启动了!本线程名:"+getName());
        for(int i=0;i<100;i++){
            System.out.println(getName()+"++"+ i);
        }

    }

    // 测试代码
    public static void main(String[] args)
    {
        // 直接创建自定的继承类
        new MyThread().start();
        new MyThread().start();
    }
}

实现 Runnable 接口

/**
 * 通过实现Runnable接口创建线程类
 */
public class MyRunnable implements Runnable   {

    @Override
    public void run() {
        System.out.println("线程启动了!");
    }

    // 测试代码
    public static void main(String[] args)
    {
        // 直接运行
        new Thread(new MyRunnable()).start();
        // 想获取当前线程的信息
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        System.out.println("线程启动了!线程的名字;"+thread.getName());
        // 匿名内部类写法
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("匿名内部类线程启动了!");
            }
        }).start();
        // JDK1.8 lambda写法
        new Thread(() -> {
            System.out.println("lambda写法匿名内部类线程启动了");
        }).start();
    }
}

实现 Callable 接口配合 Future

/**
 * 实现Callable接口配合Future创建线程
 */
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(5000);
        System.out.println("子线程名:"+Thread.currentThread().getName());
        return "返回值1";
    }

    // 测试代码
    public static void main(String[] args)
    {
        MyCallable myCallable = new MyCallable();
        // FutureTask能用来包装一个Callable或Runnable对象,因为它实现了Runnable接口,而且它能被传递到Executor进行执行
        // RunnableFuture接口同时继承Future接口和Runnable接口,在执行run()方法后,可以通过Future访问执行结果,实现类是FutureTask
        FutureTask<String> task =  new FutureTask<String>(myCallable);
        new Thread(task).start();
        try {
            //取消任务
            //task.cancel(true);
            //完成状态
            //task.isDone();
            //取消状态
            //System.out.println("子线程的取消了吗:"+task.isCancelled());
            System.out.println("子线程的返回值:"+task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

优缺点

继承 Thread 类

优点:

  • 编写简单
  • run()方法内访问当前线程,使用 this 即可

缺点:

  • 线程类不能再继承其他父类

实现 Runnable 或 Callable 接口

优点:

  • 线程类只是实现了接口,还可以继承其他类
  • 多个线程可以共享同一个 target 对象,适合多个相同线程来处理同一份资源

缺点:

  • (不算缺点的缺点)访问当前线程,则必须使用 Thread.currentThread()方法

Runnable 或 Callable 区别

Callable 方案(JDK1.5)可以理解为是 Runnable 的增强版。

区别如下:

  1. Callable 的重写方法是 call(),Runnable 的重写方法是 run()
  2. Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的
  3. Callable 的 call 方法可以抛出异常,Runnable 的 run()方法不可以
  4. Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。

提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

Future 接口提供的方法

boolean cancel(boolean mayInterruptIfRunning)

取消 Future 里关联的 Callable 任务

mayInterruptIfRunning 入参:是否允许在线程运行时中断

V get()

返回 Callable 任务里 call()方法的返回值

调用该方法将导致程序阻塞,必须等到子线程结束以后才会得到返回值

V get(long timeout, TimeUnit unit)

返回 Callable 任务里 call()方法的返回值

该方法让程序最多阻塞 timeout 和 unit 指定的时间

如果经过指定时间后,Callable 任务依然没有返回值,将会抛出 TimeoutException 异常

boolean isCancelled()

如果 Callable 任务正常完成前被取消,则返回 true

boolean isDone()

如果 Callable 任务已经完成, 则返回 true

当前文章暂无讨论,留下脚印吧!
大纲
  • 创建线程
    • 继承 Thread 类
    • 实现 Runnable 接口
    • 实现 Callable 接口配合 Future
  • 优缺点
    • 继承 Thread 类
    • 实现 Runnable 或 Callable 接口
  • Runnable 或 Callable 区别
  • Future 接口提供的方法
    • boolean cancel(boolean mayInterruptIfRunning)
    • V get()
    • V get(long timeout, TimeUnit unit)
    • boolean isCancelled()
    • boolean isDone()
提交成功,请等待审核通过后全面展示!

发表评论

昵称
邮箱
链接
签名
评论

温馨提示:系统将通过浏览器临时记忆您曾经填写的个人信息且支持修改,评论提交后仅自己可见,内容需要经过审核后方可全面展示。

选择头像