创建线程的四种方式

  • 继承Thread类
public class ThreadTest extends Thread {
    @Override
    public void run() {   
    }
  • 实现Runnable接口
public class ThreadRun implements Runnable {
    @Override
    public void run() {
    }
}
  • Thread类底层继承了Runnable接口
public class Thread implements Runnable
  • (JDK1.5以后)实现Callable接口
public class ThreadCall implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "实现了callable接口";
    }
}
  • (JDK1.5以后) 使用线程池

1,创建线程方式1与方式2的优缺点:
实现Runnable要好于继承Thread,原因:
① 实现的方式,解决单继承的局限性。
② 实现的方式针对于共享数据的情况,操作起来更方便
③ 实现的方式可以做到代码和数据的分离。
2,说说Runnable与Callable接口的异同:
相同:都是函数式接口,在类上都有@FunctionalInterface注解

@FunctionalInterface
public interface Callable<V> {
}
@FunctionalInterface
public interface Runnable {
}

不同:
1)落地方法不一致:Runnable调用run(),Callable调用call()
2)Callable可以抛异常并且有返回值,返回值类型由泛型决定,Runnable则没有
3)callable自带泛型
具体代码如下:

class MyThread implements Callable<String> {

    @Override
    public String call() {
        return "test demo!";
    }
}

class MyThread02 implements Runnable {

    @Override
    public void run() {

    }
}

(3)线程中调用run( ) 与 start( ) 方法的区别

//测试run()方法的调用:
public class ThreadTest extends Thread {
    @Override
    public void run() {
        System.out.println("线程的学习!");
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        threadTest.run();
        Thread.sleep(Integer.MAX_VALUE);
    }
}

debug运行以后,可以看到下图的运行结果:
在这里插入图片描述
分析:调用run()方法,不能说明启动线程,从截图中我们看出,该运行的程序中只有一个主线程的运行,所以说run方法调用并没有启动子线程,只是普通方法的调用。

//测试start()方法的调用:
public class ThreadTest extends Thread {
    @Override
    public void run() {
        System.out.println("线程的学习!");
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
        Thread.sleep(Integer.MAX_VALUE);
    }
}

debug运行以后,可以看到下图的运行结果:
在这里插入图片描述
分析:调用start()方法,所以底层肯定调用了run(),从截图中我们看出,该运行的程序中有两个线程的运行,一个处于运行状态,一个处于堵塞等待状态
(4)详细分析callable

public class CallableTest implements Callable<String> {
    @Override
    public String call() {
        return "实现Callable接口测试";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask(new CallableTest());
        new Thread(futureTask).start();
        System.out.println(futureTask.get()); //输出结果:实现Callable接口测试

    }
}

从运行结果上我们能够得出主线程可以拿到子线程的结果,这里的FutureTask 是一个中间的桥梁

  //FutureTask的构造器
   public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
//FutureTask间接的继承了Runnable
public class FutureTask<V> implements RunnableFuture<V> 
public interface RunnableFuture<V> extends Runnable, Future<V>
//步骤一:在FutureTask中初始化callable
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

//步骤二:Thread底层重写了runnable的接口,所以重写了run()方法,在Thread的run()里,根据不同的实现类去调用相应的run()
   @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

//步骤三:具体分析FutureTask的run()
   public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();  //调用callable的call(),获取方法返回值
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);//设置返回值
            }

(5)线程的状态
线程的状态在底层是一个枚举类实现的

public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
    }

注意:在实际开发中,我们都采用使用线程池的方式去创建线程,阿里巴巴开手册规定如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值