黑马JAVA并发编程,JUC并发编程全套教程学习笔记03-1

创建线程的方式

方式1:匿名内部类

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                log.debug("t1 start");
            }
        };

        t1.setName("t1");
        t1.start();

        log.debug("running");
    }
}

 执行结果:

对于线程来说,创建线程之后还要使用.start()方法来启动它 

方式2:使用Runnable接口

@Slf4j(topic = "c.Test2")
public class Test2 {
    public static void main(String[] args) {
        Runnable r =new Runnable() {
            @Override
            public void run() {
                log.debug("hello!");
            }
        };

        Thread t =new Thread(r, "t2");
        t.start();
    }
}

执行结果:

 

在这里可以看到,我们可以使用Runnable接口,在接口中实现run的抽象方法,再把对象r交给线程,同时也可以用线程自带的构造方法给它命名。

 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();
}

 我们可以看到,Runnable接口只有一种抽象方法。所以我们可以在这个接口上加上“@FunctionalInterface”注解,这个注解标注的接口被称为“函数式接口”,这种接口可以用lambda方法简化。

lambda表达式: 

 如下:

@Slf4j(topic = "c.Test2")
public class Test2 {
    public static void main(String[] args) {
        Runnable r =()-> {log.debug("hello!");};

        Thread t =new Thread(r, "t2");
        t.start();
    }
}

如果只有一行语句还可以像这样把花括号去掉:

@Slf4j(topic = "c.Test2")
public class Test2 {
    public static void main(String[] args) {
        Runnable r =()-> log.debug("hello!");

        Thread t =new Thread(r, "t2");
        t.start();
    }
}

异同:

在源码上,我们先看方法二的Runnable对象究竟去了哪里:

查看方法2Thread方法:发现Runnable给了init方法

点击init方法向下找发现:

然后我们可以找到:

 

target如果不为空我们就执行target的.run()方法。 

也就是说方法二其实是用的是Thread的内部方法。

而方法一其实是创建了一个子类对象,在子类对象里重写了Thread的run方法。

但是无论那种方法,其实都是调用了Thread的run方法。

小结:

方法2,将任务(Runnable)与线程(Thread)分离了,这种写法更加灵活,也更推荐这种写法

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

用 Runnable 让任务类脱离了 Thread 继承体系,更灵活。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值