Java多线程之创建线程有几种方式

    技术2025-03-16  25

    创建线程的四种方式及区别

    1. 继承Thread类2. 实现Runnable接口3. 实现Callable接口4. 线程池方式

    1. 继承Thread类

    一般步骤:

    定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。创建Thread子类的实例,即创建了线程对象子类对象调用start()方法:启动线程,然后调用run()方法

    代码示例

    /** * 定义子类并重写run方法 */ public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadDemo { public static void main(String[] args) { // 创建子类对象,即创建了一个线程 MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); // 子类对象调用start方法 t1.start(); t2.start(); // 以下操作在主线程中执行 for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } }

    这种创建方式代码简单,但因为Java是单继承一旦继承了Thread类就不能继承其他类

    2. 实现Runnable接口

    一般步骤:

    定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。创建Runnable接口实现类的实例,并以此实例作为Thread(Runnable target)的target来创建Thread对象,该Thread对象才是真正的线程对象。调用线程对象的start()方法来启动线程。

    代码示例

    /** * 定义Runnable接口实现类并重写run方法 */ public class RunnableImpl implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadDemo { public static void main(String[] args) { // 创建Runnable接口实现类对象:线程任务对象 RunnableImpl runnable = new RunnableImpl(); //创建Thread线程对象,构造方法中传递Runnable接口实现类对象 Thread t1 = new Thread(runnable); Thread t2 = new Thread(runnable); // 线程对象对象调用start方法 t1.start(); t2.start(); } }

    避免了单继承的局限性,可以继承其他类,多个线程可以共享同一个接口实现类的对象

    3. 实现Callable接口

    一般步骤:

    定义Callable接口的实现类,并重写该接口的call()方法,该call()方法的方法体同样是该线程的线程执行体,需要注意的是call()方法有返回值,并且可以抛出异常创建Callable接口实现类的对象,使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值,线程执行完成后可调用该对象的get()方法获取call()方法的返回值使用FutureTask对象作为Thread(Runnable target)的target来创建Thread对象(因为FutureTask实现了Runnable接口)调用线程对象的start()方法来启动线程如果想要获取线程执行完成后的返回值可调用FutureTask对象的get()方法

    代码示例

    /** * 定义Callable接口实现类并重写call方法 */ public class CallableImpl implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } return Thread.currentThread().getName() + "call()方法返回值"; } } public class ThreadDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { // 创建Callable接口实现类的对象 CallableImpl callable = new CallableImpl(); // 使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值 FutureTask<String> task1 = new FutureTask<String>(callable); FutureTask<String> task2 = new FutureTask<String>(callable); // 创建Thread类对象并调用start方法启动线程 new Thread(task1).start(); new Thread(task2).start(); // 获取call()方法的返回值,即线程运行结束后的返回值 String result1 = task1.get(); String result2 = task2.get(); System.out.println(result1); System.out.println(result2); } }

    实现Callable接口方式有返回值,可以抛出异常

    4. 线程池方式

    定义Callable接口的实现类,并重写该接口的call()方法,调用Executors类中的newFixedThreadPool(int n)方法创建一个线程数量为n的线程池调用线程池对象的submit()方法执行线程,返回执行结果Future对象调用FutureTask对象的get()方法获取线程执行完成后的返回值调用线程池对象的shutdown()方法关闭线程池 代码示例 public class MyStringCallable implements Callable<String[]> { private String str; public MyStringCallable(String str ){ this.str = str; } @Override public String[] call() throws Exception { return str.split(" +"); } } public class MySumCallable implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for(int x = 1; x<= 100; x++){ sum+=x; } return sum; } } public class ThreadDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { //创建有2个线程的线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); //提交执行字符串切割任务 Future<String[]> futureString = executorService.submit(new MyStringCallable("aa bbb cc d e")); System.out.println(Arrays.toString(futureString.get())); //提交执行求和任务 Future<Integer> futureSum = executorService.submit(new MySumCallable()); System.out.println(futureSum.get()); executorService.shutdown(); } }

    解决了频繁创建线程的问题,降低资源消耗实现循环利用

    Processed: 0.013, SQL: 9