• 关于java的Runableh和Clallable的笔记


      我们知道,通常创建线程的方式有继承Thread类,实现Runnable接口并重写Run()方法的实现类作为Thread的target传入参数创建线程,另外一种是实现Callable接口的实现类,实现Callable接口时,需要重写call()方法,该方法和run()类似,都是线程的执行体,但是call()方法有返回值,必须要强调的一点,如果通过target方式创建新的线程,必须要实现runnable()接口的实现类才能作为参数传入Thread类来创建线程,Callable()接口和Runnable()接口完全没有任何关系,那么怎样实现runnable接口传入呢?

        刚才讲过,实现Callable接口的类必须重写有返回值的call()方法,Callable接口是泛型接口,call()方法返回值作为Futuretask类的泛型类参数,而FutureTask类实现了Future接口和Runnable接口,(接口直接可以多继承),同时Callable接口只有一个抽象方法,所以为了便捷,可以传入Lambda表达式创建Callable对象,将Callable对象作为FutureTask类的类型参数,然后就可以作为target传入啦。

    public class Runtest {
        public static void main(String[] args) {
            Runtest test = new Runtest();
            FutureTask<Integer> task = new FutureTask<>((Callable<Integer>)()->{
               int i = 0;
               for(;i<100;i++) {
                   System.out.println(Thread.currentThread().getName()+"循环变量i的值"+i);
               }
               return i;
            });
            for(int i=0 ;i<100;i++) {
                System.out.println(Thread.currentThread().getName());
                if(i==20)
                {
                    new Thread(task,"有返回值的线程").start();
                }
            }
                try {
                    System.out.println(Thread.currentThread().getName()+"这里是我的标记");
                    
                    System.out.println("子线程的返回值:"+task.get());
                    if(task.isDone()) {
                        System.out.println("任务已经完成啦!");
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
                
            }
            
        }

    public class Runtest {
    public static void main(String[] args) {
    Runtest test = new Runtest();
    FutureTask<Integer> task = new FutureTask<>((Callable<Integer>)()->{
    int i = 0;
    for(;i<100;i++) {
    System.out.println(Thread.currentThread().getName()+"循环变量i的值"+i);
    }
    return i;
    });
    for(int i=0 ;i<100;i++) {
    System.out.println(Thread.currentThread().getName());
    if(i==20)
    {
    new Thread(task,"有返回值的线程").start();
    }
    }
    try {
    System.out.println(Thread.currentThread().getName()+"这里是我的标记");

    System.out.println("子线程的返回值:"+task.get());
    if(task.isDone()) {
    System.out.println("任务已经完成啦!");
    }
    } catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    }

    }

      既然第二种方式这么复杂,为什么还要介绍这种呢,直接实现Runnable接口不就好了吗?优势主要有:

    call()方法有返回值,并且可以抛出异常,同时Futuretask提供了一系列方法可以掌握任务的执行情况,检查计算是否完成等,也可以取消任务,相对于run()方法更为强大,

    还可以加入线程池等……

      笔记: 采用Runnable、Callable接口方式创建多线程的优缺点:

        1、线程类只是实现了Runable接口或者Callable接口,还可以继承其他类。

        2. 在这种方式下,多个线程可以共享 一个target对象,所以非常适合多个相同线程来处理同一份资源的情况。从而可以将cpu 、代码和数据分离,形成清晰地模型,较好的体现了面向对象的思想

       缺点:编程复杂。

    好好生活,天天向上
  • 相关阅读:
    golang实现单链表
    koa中间执行机制
    vuex源码简析
    从浏览器渲染过程看重绘回流
    javascript的this
    js 设计模式:观察者和发布订阅模式
    H5 移动端 键盘遮挡焦点元素解决方案
    webpack4 css modules
    Daily,一个入门级的 React Native 应用
    javascript: 类型转换
  • 原文地址:https://www.cnblogs.com/linchongatfirst/p/9043726.html
Copyright © 2020-2023  润新知