线程创建的三种方式

前言

最近,在梳理自己的知识体系,回顾基础知识,故做一下记录。

什么是线程?

说起线程,就会联想到进程,那么先来说说,什么是进程。

进程就是运行的程序。就比如说,像qq、微信我们将其打开,操作系统会给这个程序分配一定的资源(主要是内存资源),这样就是有一个qq的进程在运行。

那么,什么是线程呢。线程是CPU调度的基本单位,每个线程执行的都是某一个进程的代码的某个片段。

进程和线程有啥关系吗?一个进程里有多个线程,一个进程至少的有一个线程。

线程的创建方式

了解了什么是线程,接下来,我们看一下,线程的三种创建方式。

1、通过继承Thread类,重写run()方法创建

public class Demo {

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

}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行了");
    }
}

2、通过实现Runnable接口,实现run()方法创建

public class Demo {

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t2 = new Thread(myRunnable);
        t2.start();
        // t2.run(); 如果直接调用run()方法,其实还是在主线程(main)下在按顺序执行代码。不会创建一个新的线程去,执行run()。
    }

}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("线程执行了111");
    }
}

上边的方式,虽然也可以实现功能,但是却不那么优雅,所有我们在开发过程中,比较常用以下两种方式。
常用方式:
1)匿名内部类

public class Demo {

    public static void main(String[] args) {
    
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行了");
            }
        });
        t.start();
    }
}

2)lambda表达式

public class Demo {

    public static void main(String[] args) {
    
        Thread t = new Thread(() -> {
            System.out.println("线程执行了");
            System.out.println("--------");
        });
        t.start();
    }
}

3、通过实现Callable接口, 实现call()方法,配合FutureTask创建(此种方式可以拿到线程异步处理任务后的返回结果)

Callabe一般用于有返回结果的非阻塞的执行方法,Callable这种方式是同步非阻塞的,也就是说,按照在主线程中的代码顺序进行执行,但是当执行到callable代码片段的时候,会创建一个新的线程执行其业务逻辑,但是我们可以再主线程将要结束前,向FutuerTask询问处理结果,由于根据Callable线程处理的业务逻辑耗时不同,此时代码是阻塞的,直到Callable线程任务处理完成。

public class Demo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1、创建MyCallable
        MyCallable myCallable = new MyCallable();
        // 2、创建FutureTask,传入Callable
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        // 3、创建Thread线程
        Thread t = new Thread(futureTask);
        // 4、启动线程
        t.start();
        // 5、主线程可以执行一些业务逻辑
        System.out.println("main线程执行一些业务逻辑");
        // 6、要结果:向futureTask询问,是否处理完成。当执行到这句的时候,会进行阻塞,一直等待到线程处理完成
        Integer count = futureTask.get();
        System.out.println(count);
    }

}

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int count = 0;
        for (int i = 0; i < 100; i++) {
            count += i;
        }
        return count;
    }
}

当然,Callable的方式创建线程,我们也可以使用匿名内部类和lambda表达式
1)匿名内部类:

public class Demo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int count = 0;
                for (int i = 0; i < 100; i++) {
                    count += i;
                }
                return count;
            }
        });

        Thread t1 = new Thread(futureTask);
        t1.start();
        System.out.println("main线程执行一些业务逻辑");
        Integer count = futureTask.get();
        System.out.println("count=" + count);

    }
}

2)lambda表达式

public class Demo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            int count = 0;
            for (int i = 0; i < 100; i++) {
                count += i;
            }
            return count;
        });

        Thread t1 = new Thread(futureTask);
        t1.start();
        System.out.println("main线程执行一些业务逻辑");
        Integer count = futureTask.get();
        System.out.println("count=" + count);
    }
}

小结

在不考虑线程池创建线程的情况下,通过java创建线程只有这三种方式,可以按照需求来选择使用。同时,注意,尽量使用匿名内部类和lambda表达式来编写代码,使得代码更优雅简洁。

你可能感兴趣的:(java基础,java,开发语言)