Future实现多线程
Future是Java中的一个接口,用于异步获取任务执行结果。
在多线程编程中,可以使用Future来获取异步任务的执行结果,以便在任务完成后进行处理或展示。
使用Future实现多线程,需要以下步骤:
- 创建一个实现了Callable接口的类,实现call()方法,并在方法中编写线程执行的代码。
- 创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
- 将Callable对象提交给ExecutorService对象执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。
- 调用Future对象的get()方法获取Callable线程执行的结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。
代码示例:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class FutureDemo { public static void main(String[] args) throws Exception { // 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(10); // 提交10个Callable任务给线程池执行 List<Future<Integer>> results = new ArrayList<>(); for (int i = 0; i < 10; i++) { Callable<Integer> task = new MyTask(i); Future<Integer> result = executor.submit(task); results.add(result); } // 输出Callable任务的执行结果 for (int i = 0; i < 10; i++) { Integer result = results.get(i).get(); System.out.println("Task " + i + " result is " + result); } // 关闭线程池 executor.shutdown(); } } class MyTask implements Callable<Integer> { private int id; public MyTask(int id) { this.id = id; } public Integer call() throws Exception { System.out.println("Task " + id + " is running"); Thread.sleep(1000); // 模拟任务执行时间 return id * 10; } }
示例讲解
在以上示例中:
1.首先创建了一个线程池,然后提交10个Callable任务给线程池执行。每个Callable任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行1秒钟的任务,并返回一个结果。
2.在main函数中,使用List记录每个Callable任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取Callable任务的执行结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。
3.最后关闭线程池。
线程池实现多线程
线程池是Java中提供的一个用于管理和复用多个线程的框架,可以有效地提高多线程应用程序的性能和可靠性。
使用线程池实现多线程,通常需要以下步骤:
- 创建一个线程池,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
- 创建一个实现了Runnable接口或Callable接口的类,实现run()方法或call()方法,并在方法中编写线程执行的代码。
- 将Runnable对象或Callable对象提交给线程池执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。
- 关闭线程池,可以调用shutdown()方法或shutdownNow()方法。
代码示例:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class ThreadPoolDemo { public static void main(String[] args) throws Exception { // 创建一个包含10个线程的线程池 ExecutorService executor = Executors.newFixedThreadPool(10); // 提交10个任务给线程池执行,并记录每个任务的执行结果 List<Future<Integer>> results = new ArrayList<>(); for (int i = 0; i < 10; i++) { Callable<Integer> task = new MyTask(i); Future<Integer> result = executor.submit(task); results.add(result); } // 等待所有任务执行完成 executor.shutdown(); executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); // 输出所有任务的执行结果 int total = 0; for (int i = 0; i < 10; i++) { try { Integer result = results.get(i).get(); System.out.println("Task " + i + " result is " + result); total += result; } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { System.out.println("Task " + i + " execution error: " + e.getCause().getMessage()); } } System.out.println("Total result is " + total); } } class MyTask implements Callable<Integer> { private int id; public MyTask(int id) { this.id = id; } public Integer call() throws Exception { System.out.println("Task " + id + " is running"); Thread.sleep(2000); // 模拟任务执行时间 if (id % 2 == 0) { throw new RuntimeException("Task " + id + " execution error"); } return id * 10; } }
示例讲解:
在以上示例中,首先创建了一个包含10个线程的线程池,然后提交10个任务给线程池执行。每个任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行2秒钟的任务,并返回一个结果。
其中,如果任务的id是偶数,会抛出一个运行时异常。
在main函数中,使用List记录每个任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取任务的执行结果。
如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。
在所有任务提交给线程池后,调用ExecutorService的shutdown()方法关闭线程池,并调用awaitTermination()方法等待所有任务执行完成。
最后输出所有任务的执行结果,并计算所有任务的执行结果的总和。
总结
在多线程编程中,线程安全是一个重要的问题。后面文章会详细讲解:
1.Java中的同步机制,如synchronized关键字、Lock接口等,
2.线程之间的通信机制,如wait()、notify()、notifyAll()等。
3.程序如何避免死锁、竞态条件等问题,以确保程序的正确性和稳定性。
总之,Java多线程是提高程序并发性和响应能力的重要手段,需要掌握多线程的实现方式、同步机制、线程之间的通信机制等,以确保多线程程序的正确性和稳定性。