Java 创建线程的方法

发布时间 2023-10-26 12:46:34作者: LARRY1024

Java 中创建线程有四种方式,分别是:

继承 Thread 类

  • 首先定义一个类来继承 Thread 类,重写 run 方法。

  • 然后创建这个子类对象,并调用 start 方法启动线程。

示例:

public class ThreadDemo1 extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("thread demo1 is running");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

测试代码:

public class MainThreadDemo {
    public static void main(String[] args) {
        new ThreadDemo1().start();
    }
}

实现 Runnable 接口

  • 首先定义一个类实现 Runnable 接口,并实现 run 方法。

  • 然后创建 Runnable 实现类对象,并把它作为 target 传入 Thread 的构造函数中

  • 最后调用 start 方法启动线程。

示例:

public class ThreadDemo2 implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("thread demo2 is running");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

测试代码:

public class MainThreadDemo {
    public static void main(String[] args) {
        new Thread(new ThreadDemo2()).start();
    }
}

实现 Callable 接口,并结合 Future 实现

  • 首先定义一个 Callable 的实现类,并实现 call 方法。call 方法是带返回值的。

  • 然后通过 FutureTask 的构造方法,把这个 Callable 实现类传进去。

  • 把 FutureTask 作为 Thread 类的 target ,创建 Thread 线程对象。

  • 通过 FutureTask 的 get 方法获取线程的执行结果。

import java.util.concurrent.Callable;

public class ThreadDemo3 implements Callable<String> {
    @Override
    public String call() {
        for (int i = 0; i < 10; i++) {
            System.out.println("thread demo3 is running");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return "success";
    }
}

测试代码:

public class MainThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> task = new FutureTask<>(new ThreadDemo3());
        new Thread(task).start();
        String result = task.get();
        System.out.println(result);
    }
}

通过线程池创建线程

方式一:Runnable

  • 首先,定一个 Runnable 的实现类,重写 run 方法。

  • 然后创建一个拥有固定线程数的线程池。

  • 最后通过 ExecutorService 对象的 execute 方法传入线程对象。
    示例:

public class ThreadDemo4 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("[" + Thread.currentThread().getName() + "]:thread demo3 is running, " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

通过线程池创建线程:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class MainThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ExecutorService executorService = new ThreadPoolExecutor(
                8, 16, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy()
        );

        for (int i = 0; i < 3; i++) {
            executorService.execute(new ThreadDemo4());
        }
        executorService.shutdown();
    }
}

这种方法有一个缺点,无法对执行线程的任务传参,也没办法获取线程执行后的返回值,因此,实际使用的时候,更多的场景是使用 CompletableFuture 类去创建线程任务。

方式二:CompletableFuture

  • 使用 CompletableFuture 类去创建线程任务。

  • 然后创建一个拥有固定线程数的线程池。

  • 最后通过 CompletableFuture.supplyAsync 方法创建线程任务。

定义一个 Task 类:

public class ThreadDemo4 {

    public String count(int start, int end) {
        for (int i = start; i < end; i++) {
            System.out.println("[" + Thread.currentThread().getName() + "]: thread demo3 is running, " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return "success";
    }
}

创建线程池:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class MainThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ExecutorService executorService = new ThreadPoolExecutor(
                8, 16, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy()
        );
        List<CompletableFuture<String>> futureList = new ArrayList<>();
        List<String> results = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            int finalI = i;
            CompletableFuture<String> future = CompletableFuture
                    .supplyAsync(() -> new ThreadDemo4().count(finalI, finalI + 10), executorService)
                    .whenComplete((result, exception) -> {
                        results.add(result);
                    });
            futureList.add(future);
        }

        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(10, TimeUnit.MINUTES);
        executorService.shutdown();
        System.out.println(results);
    }
}

CompletableFuture 创建线程的时候,也是调用的ExecutorService.execute 方法创建线程任务,但是,CompletableFuture 会将线程封装为 AsyncSupply 对象,在执行结束后,保存线程的计算结果。


参考: