1.实现runnable接口
实现了,用thread去执行。
import java.lang.Runnable;
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程要执行的任务
System.out.println("Hello from Runnable!");
}
}
public class Main {
public static void main(String[] args) {
// 创建MyRunnable对象
MyRunnable myRunnable = new MyRunnable();
// 创建Thread对象,并将MyRunnable作为构造函数参数传入
Thread thread = new Thread(myRunnable);
// 启动线程
thread.start();
}
}
2.继承Thread方式
本质也是runnable接口的方式,只是其实现了runnable接口
import java.lang.Thread;
public class MyThread extends Thread {
@Override
public void run() {
// 线程要执行的任务
System.out.println("Hello from Thread!");
}
}
public class Main {
public static void main(String[] args) {
// 创建MyThread对象
MyThread myThread = new MyThread();
// 启动线程
myThread.start();
}
}
3.实现callable接口
使用futureTask去接收。
特点:
- call()可以有返回值的
- call()可以抛出异常,被外面的操作捕获,获取异常的信息
- Callable是支持泛型的
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 执行耗时的计算任务
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
public class Main {
public static void main(String[] args) {
// 创建MyCallable对象
MyCallable myCallable = new MyCallable();
// 创建FutureTask对象,并将myCallable作为构造函数参数传入
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
// 创建Thread对象,并将futureTask作为构造函数参数传入
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
try {
// 获取计算结果
Integer result = futureTask.get();
System.out.println("计算结果:" + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
4.使用线程池的方式
execute和submit的区别:
- 返回值类型:submit()方法返回一个表示任务结果的Future对象,可用于获取任务的执行结果;而execute()方法没有返回值。
- 异常处理:submit()方法可以通过Future对象的get()方法捕获Callable任务抛出的异常;而execute()方法无法直接捕获任务内部的异常,需要通过自定义的方式进行处理。
- 任务类型:submit()方法可接受Callable和Runnable类型的任务,而execute()方法只能接受Runnable类型的任务。
- 方法调用方式:submit()方法可以在任务执行之后返回一个Future对象,可以通过该对象查询任务的状态和结果;而execute()方法直接提交任务并立即执行,不返回任何结果。
4.1使用固定线程池
固定线程数量的线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("Task " + name + " is running.");
}
}
public class Main {
public static void main(String[] args) {
// 创建固定大小的线程池,线程池中有3个线程
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务给线程池
for (int i = 1; i <= 5; i++) {
MyTask task = new MyTask("Task " + i);
executor.execute(task);
}
// 关闭线程池
executor.shutdown();
}
}
4.2 周期线程池
使用Executors.newScheduledThreadPool(1)创建了一个周期线程池,其中参数1表示线程池中线程的数量。然后,使用scheduleAtFixedRate()方法提交一个周期性任务给线程池。该任务将每隔5秒运行一次。接下来,我们让主线程休眠20秒,以便观察周期性任务的执行情况。最后,我们调用shutdown()方法关闭线程池。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MyTask implements Runnable {
@Override
public void run() {
System.out.println("Task is running.");
}
}
public class Main {
public static void main(String[] args) {
// 创建周期线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
// 提交周期性任务给线程池
executor.scheduleAtFixedRate(new MyTask(), 0, 5, TimeUnit.SECONDS);
// 等待一段时间后关闭线程池
try {
Thread.sleep(20000);
executor.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4.3 缓存线程池
- 使用Executors.newCachedThreadPool()创建了一个缓存线程池。然后,循环提交5个任务给线程池进行执行。每个任务都是MyTask对象。使用execute()方法将任务提交到线程池中。
- 缓存线程池会根据需要动态地调整线程数量。如果有空闲线程可用,任务将被分配给空闲线程执行。如果没有空闲线程可用,将创建一个新线程来执行任务。如果某个线程在60秒内都没有被使用过,它将被终止并从缓存中移除。调用shutdown()方法关闭线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyTask implements Runnable {
private int taskId;
public MyTask(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running.");
}
}
public class Main {
public static void main(String[] args) {
// 创建缓存线程池
ExecutorService executor = Executors.newCachedThreadPool();
// 提交任务给线程池
for (int i = 1; i <= 5; i++) {
MyTask task = new MyTask(i);
executor.execute(task);
}
// 关闭线程池
executor.shutdown();
}
}