第三种方式实现多线程

固然Runnable接口实现多线程比继承Thread类实现多线程来的好,但是Runnable接口里的run方法并不能返回操作结果。为了解决这样的矛盾,提供了Callable接口。

JUC工具包下的Callable接口

@FunctionalInterface
public interface Callable<V>{
    public V call() throws Exceptionl;
}

call方法执行完成线程的主体功能之后(类似于Runnable的run方法)会返回值,而返回值类型由Callable接口上的泛型决定。

范例:定义一个线程主体类

class MyThread implements Callable<String>{
    private int ticket=10;//这里的变量会压入局部变量表 
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            if(this.ticket>0){
                System.out.println("sell,ticket="+this.ticket--);
            }
        }
        return "ticket has sold out!";
    }
}

此时发现我们的Thread类里面并没有提供支持Callable接口的多线程应用。

我们继续看JUC包下,JDK1.5以后有FutureTask<V>类,这个类主要是负责Callable接口对象操作,这个类的定义结构如下:

public class FutureTask<V> extends Object implements RunnableFuture<V>

而RunnableFuture接口继承了Runnable接口和Future接口

public interface RunnableFuture<V> extends Runnable,Future<V>

看JDK文档知道,Future接口有get方法
FutureTask类里有如下构造方法:

public FutureTask(Callable<V> callable)

接收Callable接口对象/继承了Callable接口对象的类,以此使得这个类能接收call方法的返回结果,从而放入值,而FutureTask又间接实现了Runnable接口和Future接口,Future接口的get方法负责取出值

完整的Callable接口实现多线程:

package TestDemo;

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

class MyThread implements Callable<String>{
    private int ticket=10;//这里的变量会压入局部变量表 
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            if(this.ticket>0){
                System.out.println("sell,ticket="+this.ticket--);
            }
        }
        return "ticket has sold out!";
    }
}

public class TestDemo{
    
    public static void main(String[] args)throws Exception{
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();

        FutureTask<String> task1=new FutureTask<String>(mt1);//FutureTask构造方法接收Callable接口对象或其实现
        FutureTask<String> task2=new FutureTask<String>(mt2);

        //FutureTask是Runnable接口的实现类/子类,所以Thread构造方法能接收其对象
        new Thread(task1).start();//多线程启动
        new Thread(task2).start();//多线程启动

        //FutureTask同时是Future接口的实现类/子类,父接口的get方法可以获取值
        System.out.println("A:"+task1.get());
        System.out.println("B:"+task2.get());
        
    }
}

结果:


9003228-12188f0d58b50882.png
image.png

第三种方式的实现麻烦在于既要接收返回值信息,并且又要与原始的多线程的实现靠拢(Threadl类)

总结:

1.对于多线程的实现,重点在于Runnable和Thread类
2.Callable接口之后也会又诸多应用

猜你喜欢

转载自blog.csdn.net/weixin_34081595/article/details/87523548