農農  

线程实现方式:
  1.继承Thread类
  2.实现Runnable接口
  3.线程池
  4.Callable

 

无论使用继承Thread类还是实现Runnable接口,还是使用线程池都无法解决这两个问题

    /*
    run方法没有方法 返回值
    run方法不能抛异常,如果想要解决异常,只能 用try-catch
     */
    @Override
    public void run() {
        System.out.println("线程执行的run方法,没有返回值不能,不能抛异常");
    }

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

 

解决如上两个问题需要用到Callable,Callable和Runnable类似,在JUC包下,主要区别在于Callable中的call方法可以带返回值并且可以抛异常,如果需要执行Callable,需要Future实现类的支持,能够接受返回值结果,FutureTask是Future实现类

  解决方案一: 

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常");
        return "callable";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable=new MyCallable();
        //利用FutureTask执行Callable并且接受结果
        FutureTask<String> stringFutureTask = new FutureTask<>(myCallable);
        //利用线程执行Task任务
        new Thread(stringFutureTask).start();
        //接收结果FutureTask.get会发生阻塞
        System.out.println(stringFutureTask.get());
        System.out.println("MyCallable执行完毕,返回值结果正确接收~");
    }
}

 

  控制台结果:

 

 

 

  方解决方案二:

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常");
        return "callable";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {       
        //方式二
        MyCallable myCallable=new MyCallable();
        //创建一个线程池
        ExecutorService executorService= Executors.newFixedThreadPool(3);
        //创建线程执行额任务,接收任务结果
        Future<String> future=executorService.submit(myCallable);
        //接收返回值
        System.out.println(future.get());
        System.out.println("方式二:线程池:MyCallable执行完毕,返回值结果正确接收");

        //停止线程池
        executorService.shutdown();
    }
}

 

  控制台结果 :

 

Future.get()方法获取任务执行结果,该方法如果没有返回时,暂时处于阻塞状态
Future.get(Long timeOut,TimeUnit timeUnit)可以设置超时时间
Future.boolean isDone()如果线程结束,无论是正常结束还是任务终止都会返回true
Future.boolean isCanceller()如果任务完成前被取消则返回true
Future.boolean cancel(boolean flag),方法参数如果传入为true代表中断任务,如果任务中断成功,则返回值为true,

  如果失败则为false

 

 

  Future提供三种功能:1.中断任务cancel(true)        2.判断任务是否执行完成isDone()  

  3.编写测试代码:

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常");
        return "callable";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        //方式二
        MyCallable myCallable=new MyCallable();
        //创建一个线程池
        ExecutorService executorService= Executors.newFixedThreadPool(3);
        //创建线程执行额任务,接收任务结果
        Future<String> future=executorService.submit(myCallable);
        //中断任务
        boolean cancel = future.cancel(true);

        if (cancel==true){
            System.out.println("中断任务成功");
        }else{
           System.out.println(future.get(2000,TimeUnit.MILLISECONDS));
        }

        //接收返回值
        System.out.println(future.get());
        System.out.println("方式二:线程池:MyCallable执行完毕,返回值结果正确接收");

        //停止线程池
        executorService.shutdown();
    }
}

  

  控制台结果:

 

 


  如果让手写Future模式应该怎么样定义

//FLAG相当于数据标识,如果放入数据成功,则返回为true,否则返回为false
    private static boolean FLAG=false;
    private String data;

    public synchronized void setData(String data) throws InterruptedException {
        Thread.sleep(2000);
        //赋值操作
        this.data = data;
        FLAG=true;
        //唤起
        notify();
    }

    public synchronized String getData() {
        //如果获取数据失败
        if(!FLAG){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void main(String[] args) {
        MyFuture future=new MyFuture();
        new Thread(()->{
            try {
                future.setData("张三");
                System.out.println(future.getData());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

 

posted on 2020-03-23 17:00  Baekhyunne  阅读(142)  评论(0编辑  收藏  举报