多线程的四种创建方式
1、继承Thread类
步骤:
-
创建一个类,继承自
java.lang.Thread
类。 -
重写
run()
方法,在run()
方法中定义线程要执行的任务。 -
创建该类的实例,然后调用
start()
方法来启动线程。
代码:
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程执行中:" + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
MyThread类继承了Thread类,重写了run方法,在run方法中,通过循环打印值,在main方法中,创建了MyThread类的一个实例myThread,然后调用run()方法来执行线程的任务
2、实现runnable接口
步骤:
-
创建一个类实现
java.lang.Runnable
接口。 -
实现
run()
方法,在其中定义线程要执行的任务。 -
创建
Runnable
接口实现类的实例,将其作为参数传递给Thread
类的构造函数来创建Thread
对象,最后调用start()
方法启动线程
代码:
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("通过Runnable接口实现的线程执行中:" + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
MyRunnable类 实现了Runnable 接口,重写了run方法
在main方法中,先创建了MyRunnable 类的实例myRunnable ,然后把该实例作为参数传递给Thread 类的构造函数创建Thread 对象thread,最后调用start()方法启动线程
这种方式的好处是可以实现多个线程共享同一个Runnable 实例的资源,避免了单继承的限制
3、实现callable接口(与 Future 和 FutureTask 结合使用)
步骤:
-
创建一个类实现
java.util.concurrent.Callable
接口,该接口是一个泛型接口,需要指定返回值类型。 -
实现
call()
方法,在其中定义线程要执行的任务,并返回一个结果。 -
创建
Callable
接口实现类的实例,将其作为参数传递给FutureTask
类的构造函数(FutureTask
实现了RunnableFuture
接口,而RunnableFuture
继承了Runnable
和Future
接口)。 -
将
FutureTask
对象作为参数传递给Thread
类的构造函数来创建Thread
对象,最后调用start()
方法启动线程。可以通过FutureTask
的get()
方法获取Callable
线程执行后的结果(get()
方法会阻塞,直到线程执行完成并返回结果)。
代码:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyCallable myCallable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("线程执行结果:" + futureTask.get());
}
}
-
MyCallable
类实现了Callable<Integer>
接口,在call()
方法中计算了 0 到 9 的整数和并返回结果。 -
在
main
方法中,创建了MyCallable
类的实例myCallable
,然后将其作为参数传递给FutureTask
类的构造函数创建FutureTask
对象futureTask
。接着将futureTask
作为参数传递给Thread
类的构造函数创建Thread
对象thread
并启动。最后通过futureTask.get()
方法获取线程执行后的结果,get()
方法会阻塞当前线程,直到call()
方法执行完成并返回结果 -
Callable 接口类似于 Runnable 接口,不过它可以返回一个结果并且可以抛出异常
4、使用线程池(通过 Executor 框架)
步骤:
-
创建一个线程池,例如使用
ThreadPoolExecutor
类或者通过Executors
工厂类来创建。 -
创建
Runnable
或Callable
接口实现类的实例,作为任务提交给线程池。 -
线程池中的线程会自动执行这些任务,执行完成后可以关闭线程池。
代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnableForPool implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程池中的线程执行中:" + i);
}
}
}
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
MyRunnableForPool myRunnable = new MyRunnableForPool();
executorService.submit(myRunnable);
}
executorService.shutdown();
}
}
-
MyRunnableForPool
类实现了Runnable
接口,定义了线程要执行的任务 -
在
main
方法中,首先通过Executors.newFixedThreadPool(3)
创建了一个包含 3 个线程的线程池executorService
。然后循环 5 次,每次创建一个MyRunnableForPool
类的实例并通过executorService.submit()
方法提交给线程池执行。最后调用executorService.shutdown()
方法来关闭线程池,它会等待所有已提交的任务执行完成后再关闭线程池。这种方式便于管理和复用线程,提高了资源利用率