一步一步源码分析线程创建

创建线程

方法1,直接Thread

// 创建线程对象
Thread t = new Thread() {
 public void run() {
 // 要执行的任务
 }
};
// 启动线程
t.start();

方法2,使用 Runnable 配合 Thread

把【线程】和【任务】(要执行的代码)分开

  • Thread 代表线程
  • Runnable 可运行的任务(线程要执行的代码)
Runnable runnable = new Runnable() {
 public void run(){
 // 要执行的任务
 }
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start(); 

也可使用lambda表达式

// 创建任务对象
Runnable task2 = () -> log.debug("run...");

方法3,FutureTask 配合 Thread

FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况

// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
 log.debug("run");
 return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t5=new Thread(task3, "t5");
 t5.start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);
19:22:27 [t3] c.ThreadStarter - run
19:22:27 [main] c.ThreadStarter - 结果是:100

例子测试

public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread t1 =new Thread("t1"){
            @Override
            public void run() {
                log.debug("t1.run...");
            }
        };
        t1.start();
        Runnable task1=new Runnable() {
            @Override
            public void run() {
                log.debug("t2.run...");
            }
        };
        Thread t2=new Thread(task1,"t2");
        t2.start();
        Runnable task2=()->{log.debug("t3.run...");};
        Thread t3=new Thread(task2,"t3");
        t3,start();
	
        Thread t4=new Thread(()->{log.debug("t4.run...");},"t4");
        t4.start();

        // 创建任务对象
        FutureTask<Integer> task3 = new FutureTask<>(() -> {
            log.debug("hello");
            return 100;
        });
    // 参数1 是任务对象; 参数2 是线程名字,推荐
        Thread t5=new Thread(task3, "t5");
        t5.start();
    // 主线程阻塞,同步等待 task 执行完毕的结果
        Integer result = task3.get();
        log.debug("结果是:{}", result);

    }

在这里插入图片描述

源码分析

Thread与Runnable

  • Runnable只是一个接口
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

*在创建线程时,Thread的构造方法

 public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
  • init是重写的方法
private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null);
    }
private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name.toCharArray();

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

中间有一行是this.target=target;
将Runnable的对象赋值。

  • 调用start方法
public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
  • start0方法
private native void start0();

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

最后一个是重点,前面target赋值了,所以不为null可以使用Runnable的run方法

FutureTask与Thread

  • FutureTask实现了RunnableFuture< V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
  • RunnableFuture< V>继承了Runnable,所以可以当作参数传输到Thread里面
  • 而且它又继承了Future< V>,里面有get方法可以获得返回值
V get() throws InterruptedException, ExecutionException;
  • FutureTask构造时传输了Callable< V>参数,Callable < V > 和Runnable有点像,只是Callable< V >有返回值
    Callable < V >
@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;
}
  • FutureTask在Thread中过程是一样的,最后调用了 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();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

因为通过FutureTask的构造函数初始化了Callable的对象且state赋值了NEW,所以直接进if语句,来调用Callable的call方法,并返回值

结语

Runnable与FutureTask在Thread中过程是一样的,只是前者在新建时将要运行的代码重写到了run方法里面,而FutureTask通过传参Callable并将要运行的代码重写到了Callable的call方法里面,FutureTask内部通过重写继承的Runnable的run方法来调用了Callable的call方法来实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值