多线程1(面试题--常见的线程创建方式)

1.创建子类,继承Thread,重写run方法

2.创建子类,实现Runnable接口,重写run方法

3.继承Thread,使用匿名内部类

4.实现Runnable,使用匿名内部类

5.lambda表达式(推荐)


继承Thraed重写run

步骤:继承->重写->实例->启动

缺点:线程和任务绑定在一起

java 复制代码
//1.继承
class MyThread extends Thread{
    //2.重写

    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        //MyThread thread = new MyThread();

        //3.实例
        Thread thread = new MyThread();

        //4.启动
        thread.start();

        while (true){
            System.out.println("hello main");
            Thread.sleep(2000);
        }
    }
}

实现Runnable重写run

步骤其实大差不差,区别在于,不仅要实例化Thread对象,还要实例化Runnable对象,将Runnable对象作为参数传给Thread

通俗一点来说就是,Runnable是单独描述线程要执行的任务的,此时与线程没关系,将其作为参数传给Thread就是告诉线程所要执行的任务是什么,两者之间解耦合度更高,而第一种方法是将线程和任务绑定在了一起,耦合度更高

java 复制代码
class MyRunnable implements Runnable{

    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);

        thread.start();

        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

3.继承Thread,使用匿名内部类

本质上跟第一种方法没区别,只不过使用了匿名内部类来创建线程,好处就在于这个类是一次性的,只使用一次,也就是跟着当前线程一起,线程结束,类也结束

java 复制代码
public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();//真正创建线程

        while(true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

4.实现Runnable,使用匿名内部类

java 复制代码
public class Demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        t.start();

        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

注意写法即可


5.lambda表达式

这是更推荐的一种做法,更加简洁

java 复制代码
public class Demo5 {
    public static void main(String[] args) {
        //lambda
        Thread thread = new Thread(()->{
           while (true){
               System.out.println("hello thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        thread.start();

        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

使用lambda表达式需要注意的是变量捕获的情况:final 事实final(没有被修改的变量)


问题:为什么在继承或实现Runnable的时并不需要导包呢?

是因为他们都属于lang包底下,在Java中,lang包会默认导入到项目中,因此不需要手动import

这是基于管理方便的缘故,用什么类就导入什么包,但也存在这种方便的,默认自动导入的lang包

相关推荐
掘金安东尼2 小时前
本周前端与 AI 技术情报|前端下一步 #462
前端·javascript·面试
敖正炀3 小时前
ArrayBlockingQueue深度解析
java
敖正炀3 小时前
LinkedBlockingQueue详解
java
敖正炀3 小时前
SynchronousQueue 详解
java
wuyikeer3 小时前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
努力努力再努力wz3 小时前
【Linux网络系列】深入理解 I/O 多路复用:从 select 痛点到 poll 高并发服务器落地,基于 Poll、智能指针与非阻塞 I/O与线程池手写一个高性能 HTTP 服务器!(附源码)
java·linux·运维·服务器·c语言·c++·python
努力努力再努力wz3 小时前
【Linux网络系列】万字硬核解析网络层核心:IP协议到IP 分片重组、NAT技术及 RIP/OSPF 动态路由全景
java·linux·运维·服务器·数据结构·c++·python
LaLaLa_OvO3 小时前
mybatis 引用静态常量
java·mybatis
Han_han9193 小时前
常用API:
java·开发语言