- 实现 Runnable 接口
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的代码
}
}
然后在主线程中创建一个线程对象,并启动该线程:
Thread thread = new Thread(new MyRunnable());
thread.start();
- 继承 Thread 类
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
}
}
然后在主线程中创建该线程对象,并启动该线程:
MyThread thread = new MyThread();
thread.start();
在上述两种方式中,都需要在一个独立的线程中运行代码,这就要求我们将需要多线程执行的代码放到一个特定的代码块或方法中,然后将其作为参数传递给 Thread 或 Runnable 对象。
需要注意的是,在使用多线程时,应该避免线程之间的冲突和数据竞争。可使用同步机制,如 synchronized 关键字、Lock 对象等来保证线程安全。
同时,Java 还提供了一些线程池的实现,如 ThreadPoolExecutor 等,用于管理多个线程的执行和资源分配。
java线程池的创建
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建固定大小的线程池,同时运行5个线程
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交任务到线程池执行
for (int i = 0; i < 10; i++) {
final int taskId = i;
executorService.execute(() -> {
System.out.println("Task " + taskId + " is being executed by " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " has been completed.");
});
}
// 关闭线程池
executorService.shutdown();
}
}
这个代码示例创建了一个包含 5 个线程的固定大小线程池。然后,通过循环提交了10个任务到线程池中执行。每个任务会打印自己的任务号和正在执行的线程名称,并模拟了一个耗时的任务。
@Asycn注解搭配线程池的使用
首先,在你的 Spring Boot 应用主类中加上 @EnableAsync
注解开启异步方法执行功能:
@SpringBootApplication
@EnableAsync // 开启异步方法执行功能
public class MyApplication {
// ...
}
然后,定义一个用于执行异步任务的线程池:
@Configuration
public class ThreadPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(25); // 队列容量
executor.setKeepAliveSeconds(300); // 线程池维护线程所允许的空闲时间
executor.setThreadNamePrefix("my-pool-"); // 线程名前缀
executor.initialize(); // 初始化 executor
return executor;
}
}
在上面的代码中,通过 ThreadPoolTaskExecutor
类创建了一个线程池,并设置了一些常用参数,例如核心线程数、最大线程数、队列容量等。
接下来,我们定义一个异步任务,使用 @Async
注解标记它为异步方法:
@Service
public class MyService {
@Async("taskExecutor") // 使用名为 "taskExecutor" 的线程池执行该方法
public void asyncMethod() {
System.out.println("异步方法被调用,线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟一个耗时的操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步方法执行完成。");
}
}
在上面的代码中,我们使用 @Async
注解,指定了要使用的线程池名称为 "taskExecutor",然后定义了一个异步任务,其中包含了一些打印和模拟耗时操作的代码。
最后,我们在 Controller 中调用异步方法:
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/async")
public String async() {
myService.asyncMethod(); // 调用异步方法
return "Async method is being executed.";
}
}
在上面的代码中,我们注入了 MyService
服务实例,并在 /async
请求处理器中调用了异步方法 asyncMethod()
。
运行应用程序,访问 /async
URL,我们会看到异步方法被调用,但是不会阻塞主线程,而是在另一个线程池里执行。同时,在控制台输出中,我们可以看到异步方法执行完成的消息。