线程启动方式
在 Java 里,线程启动方式主要有以下几种:
1. 继承 Thread
类
这是最基础的启动线程的方式,通过继承 Thread
类,重写 run()
方法来定义线程要执行的任务,接着创建该类的实例并调用 start()
方法启动线程。
class MyThread extends Thread { @Override public void run() { System.out.println("继承 Thread 类的线程正在执行,线程名:" + Thread.currentThread().getName()); } } public class ThreadInheritanceExample { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
代码解释:
MyThread
类继承了Thread
类,并重写了run()
方法,此方法包含了线程要执行的具体任务。- 在
main
方法中,创建了MyThread
类的实例myThread
,然后调用start()
方法启动线程。
2. 实现 Runnable
接口
实现 Runnable
接口,重写 run()
方法,再把该实现类的实例作为参数传递给 Thread
类的构造函数,最后调用 start()
方法启动线程。
class MyRunnable implements Runnable { @Override public void run() { System.out.println("实现 Runnable 接口的线程正在执行,线程名:" + Thread.currentThread().getName()); } } public class RunnableImplementationExample { 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()
方法启动线程。
3. 实现 Callable
接口
实现 Callable
接口,重写 call()
方法,该方法可以有返回值。借助 FutureTask
类来包装 Callable
对象,再把 FutureTask
对象作为参数传递给 Thread
类的构造函数,最后调用 start()
方法启动线程。
import java.util.concurrent.*; class MyCallable implements Callable<String> { @Override public String call() throws Exception { return "实现 Callable 接口的线程执行完毕,线程名:" + Thread.currentThread().getName(); } } public class CallableImplementationExample { public static void main(String[] args) { MyCallable myCallable = new MyCallable(); FutureTask<String> futureTask = new FutureTask<>(myCallable); Thread thread = new Thread(futureTask); thread.start(); try { String result = futureTask.get(); System.out.println(result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }
代码解释:
MyCallable
类实现了Callable
接口,并重写了call()
方法,该方法返回一个String
类型的结果。- 在
main
方法中,创建了MyCallable
类的实例myCallable
,使用FutureTask
类包装myCallable
,创建Thread
类的实例thread
并启动线程。 - 调用
futureTask.get()
方法获取线程执行的结果,此方法会阻塞当前线程,直至线程执行完毕。
4. 使用线程池
线程池可以管理和复用线程,避免频繁创建和销毁线程带来的性能开销。通过 ExecutorService
接口和 Executors
工具类可以创建不同类型的线程池。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class MyRunnableForThreadPool implements Runnable { @Override public void run() { System.out.println("线程池中的线程正在执行,线程名:" + Thread.currentThread().getName()); } } public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); MyRunnableForThreadPool myRunnable = new MyRunnableForThreadPool(); executorService.submit(myRunnable); executorService.submit(myRunnable); executorService.shutdown(); } }
代码解释:
MyRunnableForThreadPool
类实现了Runnable
接口,并重写了run()
方法。- 在
main
方法中,使用Executors.newFixedThreadPool(2)
创建了一个固定大小为 2 的线程池executorService
。 - 调用
executorService.submit(myRunnable)
方法将任务提交给线程池执行。 - 最后调用
executorService.shutdown()
方法关闭线程池。
这几种线程启动方式各有优缺点,在实际应用中,要依据具体需求来选择合适的启动方式。
JUC编程 文章被收录于专栏
JUC 是 Java.util.concurrent 包的简称,它是 Java 5 引入的一个用于处理并发编程的工具包,为 Java 开发者提供了一系列用于高效处理并发任务的类和接口,极大地简化了多线程编程的复杂性。