java——线程创建与Callable接口解析

Java的线程创建方法

在Java当中,最基本的线程创建方法有两种,一种是通过继承Thread类,重写run方法:

class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("this is MyThread!");
        }
    }

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

另外一种是实现Runnable接口,重写run方法:

class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("this is MyRunnable!");
        }
    }


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

上述两种方式都能创建一个线程,并启动运行。查看Thread的源码,发现Thread是一个Runnable的子类,因此需要实现Ruannable的run方法,所以我们继承Thread重写的run方法实际上就是Runnable的run方法。

class Thread implements Runnable {
	private Runnable target;
	@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
}

另外,Thread内还有一个start方法,从start方法的注释可以知道,调用该方法时,虚拟机会创建一个线程,并默认执行Thread的run方法。

/**
 * Causes this thread to begin execution; the Java Virtual Machine
 * calls the <code>run</code> method of this thread.
 * */
public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);

        boolean started = false;
        try {
        	//一个本地方法,java本地调用的接口,用于创建线程
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            
            }
        }
    }

因此,两种线程创建方式都是利用了在执行start方法启动线程时,会默认调用run方法的特性:

  • 我们通过继承Thread类重写run方法的方式创建线程时,调用start方法,虚拟机创建了线程,由于我们重写了run方法,因此执行的是我们的方法,而不是Thread类内target属性的run方法;
  • 我们通过实现Runnable接口创建线程时,Thread的构造函数会将我们实现的Runnable对象,赋值给Thread类内的target属性,调用Thread的start方法,由虚拟机创建线程,因为我们没有重写Thread的run方法,所以执行的是Thread的run方法,但是该方法调用了target的run方法,因此我们实现的Runnable的run方法得以执行

Callable接口说明

上述的两种线程创建方法都重写了run方法,但是run方法没有返回参数,对于需要线程返回计算结果的情况,
JDK提供了Callable的接口,Callable接口定义了一个带返回值的call方法,并且返回值是类型参数:

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

因此,通过Callable接口,再结合线程池,可以实现线程返回一个Future对象,通过该对象可以获取计算结果。注意:Future的get方法,是一个阻塞方法。

class MyCallable implements Callable<String>{
        @Override
        public String call() throws Exception{
            Thread.sleep(2000);
            return " world!";
        }
    }

    public static void main(String[] args) throws Exception{
        ExecutorService executorService=Executors.newSingleThreadExecutor();
        MyCallable myCallable=new MyCallable();
        Future<String> result =executorService.submit(myCallable);
        System.out.println("hello "+result.get());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值