java线程创建的四种方式

继承Thread类

继承Thread类:您可以创建一个新的类,继承自Thread类,并重写run()方法。然后,您可以创建该类的实例,并调用start()方法来启动新线程。

1
2
3
4
5
6
7
8
9
10
class MyThread extends Thread {
public void run() {
// 线程执行的代码
}
}

// 创建并启动线程
MyThread thread = new MyThread();
thread.start();

实现Runnable接口

您可以实现Runnable接口并实现其run()方法。然后,您可以创建Thread类的实例,将实现了Runnable接口的对象作为参数传递给Thread的构造函数,并调用start()方法启动新线程。

1
2
3
4
5
6
7
8
9
class MyRunnable implements Runnable {
public void run() {
// 线程执行的代码
}
}

// 创建并启动线程
Thread thread = new Thread(new MyRunnable());
thread.start();

实现 Callable 和 Future 接口创建线程

当您需要在多个线程中执行一些任务,并且希望获取它们的执行结果时,可以使用Callable和Future接口。Callable用于定义可调用的任务,而Future用于获取任务的执行结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<Integer> {
public Integer call() throws Exception {
// 执行任务并返回结果
return 42;
}
}

public class Main {
public static void main(String[] args) {
// 创建Callable任务
Callable<Integer> callable = new MyCallable();

// 创建FutureTask,并将Callable任务作为参数传递给它
FutureTask<Integer> futureTask = new FutureTask<>(callable);

// 创建线程,并将FutureTask作为参数传递给它
Thread thread = new Thread(futureTask);

// 启动线程
thread.start();

// 在将来获取任务的执行结果
try {
Integer result = futureTask.get();
System.out.println("执行结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

在这个示例中,我们首先创建了一个实现Callable接口的MyCallable类,其中的call()方法执行了任务并返回结果。然后,我们创建了一个FutureTask对象,将MyCallable对象作为参数传递给它。接下来,我们创建了一个线程,并将FutureTask对象作为参数传递给它。最后,通过调用futureTask.get()方法获取任务的执行结果。

请注意,futureTask.get()方法是阻塞的,直到任务执行完成并返回结果。如果任务还没有完成,调用get()方法的线程将被阻塞。您还可以使用isDone()方法来检查任务是否已经完成。

使用线程池创建

在Java中,使用线程池创建线程可以有效地管理和复用线程资源,提高应用程序的性能和效率。Java提供了多种方式来创建线程池,下面详细介绍了这些方法:

newFixedThreadPool(int nThreads)

创建一个固定大小的线程池,线程数量为指定的大小。如果提交的任务数量超过线程池的大小,任务将被放入等待队列中,直到有可用的线程来执行。

1
2
3
4
5
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService executor = Executors.newFixedThreadPool(5);

newCachedThreadPool()

创建一个可根据需要自动扩展的线程池。线程池的大小根据提交的任务数量动态调整。如果有空闲线程可用,就重用它们;如果没有可用的线程,则创建一个新线程。

1
2
3
4
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService executor = Executors.newCachedThreadPool();

newSingleThreadExecutor()

创建一个只有一个线程的线程池。该线程池保证所有任务按照顺序执行,即使提交的任务是并发的,也会按照先后顺序执行。

1
2
3
4
5
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService executor = Executors.newSingleThreadExecutor();

newScheduledThreadPool(int corePoolSize)

创建一个定时任务的线程池,可以用于执行延迟任务或定时任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);

// 延迟执行任务
executor.schedule(() -> {
// 任务执行的代码
}, 1, TimeUnit.SECONDS);

// 定时执行任务
executor.scheduleAtFixedRate(() -> {
// 任务执行的代码
}, 0, 1, TimeUnit.SECONDS);

提交任务

这些方法返回的是实现了ExecutorService接口的线程池对象,您可以使用该对象提交任务并管理线程池。

使用线程池的好处是可以重用线程,避免频繁创建和销毁线程的开销,提高线程的利用率。此外,线程池还提供了任务调度、线程管理、线程超时等额外的功能。

无论使用哪种线程池创建方法,都可以使用execute()方法或submit()方法提交任务给线程池执行。例如:

1
2
3
4
5
6
7
8
9
10
executor.execute(() -> {
// 执行的任务代码
});

// 或者

Future<?> future = executor.submit(() -> {
// 执行的任务代码
});

以上是Java中使用线程池创建线程的常用方法。您可以根据实际需求选择合适的线程池类型和方法来创建和管理线程。

Author: suce
Link: https://haoubox.cn/2021/06/05/java线程创建的四种方式/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.