Java线程创建的三种玩法

Thread与Runnable的爱恨情仇

Thread线程类实现了Runnable接口

Runnable接口中有一个抽象方法run()

Thread对其进行实现

  • target是Runnable任务,可以在创建线程时传入,不传入又没有重写run方法的话,run方法就是个空方法,线程启动后什么也不会做。

1. 直接使用Thread

class Main{
    public static void main(String[] args){
        //t1为线程名    
        Thread t = new Thread("t1") {
            //重写run方法
            @Override
            public void run() {
                //要执行的任务
                //...
            }
        };

        //启动线程
        t.start();
    }

}

这里是用了匿名内部类的方式,创建了Thread的子类,并重写了run方法。如果不重写run方法,那么线程启动后不会执行任务。

记得要启动线程。

2. 先创建Runnable,再创建Thread

@Slf4j(topic = "c.Test")
public class Test {
    public static void main(String[] args) {
       Runnable r = new Runnable() {
           @Override
           public void run() {
               log.debug("running...");
           }
       };
       
       //传入任务对象 "t1"为线程名
       Thread t = new Thread(r,"t1");
       t.start();
    }
}

这里是用匿名内部类的方式创建了Runnable接口的实现类,因为Runnable接口中定义了抽象方法run(),所以必须对其进行实现。

在创建线程时传入Runnable对象,它就是Thread类中的成员属性target。

简化

Runnable接口是一个函数式接口,它被@FunctionalInterface注解修饰,它里面只有1个抽象方法,可以用lambda表达式简化。

@Slf4j(topic = "c.Test")
public class Test {
    public static void main(String[] args) {
       Runnable r = () -> {
           log.debug("running...");
           log.debug("end...");
       };
        
       Thread t = new Thread(r,"t1");
       t.start();
    }
}
前两种创建方式的对比

第一种是把线程和任务合并在一起,第二种将线程和任务分离。

使用Runnable更容易与线程池等高级API结合。

用Runnable把任务从线程继承体系中分离,更加灵活。

3. 结合FutureTask,带返回结果

如果想要获得任务的返回结果,可以结合FutureTask创建线程。

FutureTask实现了RunnableFuture接口

RunnableFuture接口又继承自Runnable接口和Future接口。

所以FutureTask间接地实现了Runnable接口,也是任务对象。它也可以作为任务对象在创建Thread时被传入。

@Slf4j(topic = "c.Test")
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> f  = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 8 + 18;
            }
        }); 
        
        Thread t = new Thread(f,"t1");
        t.start();
        log.debug("{}", f.get());
    }
}

要有返回值,构造FutureTask时要传入Callable对象。使用get()方法获取返回值。

Callable也是一个函数式接口,也可以用lambda表达式简化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值