Java多线程(一)---- 创建与使用

JUC

Java多线程是一个非常复杂的知识点,今天这篇我们就来说说Java多线程的多种实现方式吧。

Thread

构造

Thread类可以说是非常基础的一个类了,通过继承Thread类,我们可以成功的创建一个“线程类”。

public class threadDemo {
    public static class threadDemo extends Thread {
        @Override
        public void run() {
            System.out.println("threadDemo");
        }
    }

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

翻看源码,我们不难发现:我们在调用无参构造时,实际上调用的是Thread类中的私有构造方法。

@SuppressWarnings()用于抑制编译器产生的警告信息。Removal warnings (§9.6.4.6) are specified by the string "removal".为官网对于removal的描述。

为什么在Java8中源码是调用一个普通的私有函数init进行初始化,但在17中却使用了私有的构造函数进行初始化呢?这两个方式有什么区别呢?

有一种解释是,使用私有函数init的方式仍然会被反射破坏他的封装性,使用私有的构造函数可以彻底隐藏其初始化细节,保证他的封装性。

Runnable

实现

实现Runnable接口也可以构造一个“线程类”。

public class Demo {
    public static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println("MyThread");
        }
    }

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

        // Java 8 函数式编程,可以省略MyThread类
        new Thread(() -> {
            System.out.println("Java 8 匿名内部类");
        }).start();
    }
}

那么使用Runable接口的构造底层是什么样的呢?

看了源码我们才发现,原来他调用的同样是Thread类的构造方法,不过这一次他用的是public Thread(Runnable target)有参构造方法。

Thread 和 Runable的区别

  • 由于Java“单继承,多实现”的特性,Runnable接口使用起来比Thread类更灵活。(当然这里的单继承是指类的继承,接口是可以多继承的)

  • Runnable接口出现更符合面向对象,将线程单独进行对象的封装。

  • Runnable接口出现,降低了线程对象和线程任务的耦合性。

  • 如果使用线程时不需要使用Thread类的诸多方法,显然使用Runnable接口更为轻量。

因此,我们通常优先使用实现Runnable接口这种方式来自定义线程类。

Callable、Future和FutureTask

上面两种方法虽然可以成功创建线程类,但他们有一个共同的缺点--run()没有返回值。这时候就需要Callable和Futrure了。我们通过FutureTask类去使用他们。

Callable接口和Runnable类似,只是他多了一个返回值,同时他的方法是call()。

Future则保存异步计算的结果。

FutureTask实现了RunnableFuture接口,而这个接口继承了Runable和Future两个接口。

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "执行结果: " + Thread.currentThread().getName();
    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<String>(new MyCallable());
        Thread thread = new Thread(futureTask);//futureTask作为构造函数参数时,是Runable
        thread.start();
        System.out.println(futureTask.get());  //作为结果储存时,是Future
    }
}
posted @ 2025-03-11 17:44  tripl3T  阅读(37)  评论(0)    收藏  举报