线程池_实现多线程方式四

发布时间:2026/6/30 4:16:04
线程池_实现多线程方式四 问题:之前来一个线程任务,就需要创建一个线程对象去执行,用完还要销毁线程对象,如果线程任务多了,就需要频繁创建线程对象和销毁线程对象核心问题,这样会耗费内存资源,所以我们就想线程对象能不能循环利用,用的时候直接拿线程对象,用完还回去1.如何创建线程池对象:工具类- Executors 2.获取线程池对象:Executors中的静态方法: static ExecutorService newFixedThreadPool(int nThreads) a.参数:指定线程池中最多创建的线程对象条数 b.返回值ExecutorService 是线程池,用来管理线程对象 3.执行线程任务: ExecutorService中的方法 Future? submit(Runnable task) 提交一个Runnable任务用于执行 FutureT submit(CallableT task) 提交一个Callable任务用于执行 4.submit方法的返回值:Future接口 用于接收run方法或者call方法返回值的,但是run方法没有返回值,所以可以不用Future接收,执行call方法需要用Future接收 Future中有一个方法:V get() 用于获取call方法返回值 5. ExecutorService中的方法: void shutdown() 启动有序关闭其中先前提交的任务将被执行但不会接受任何新任务 6. 实现细节 1.创建n个线程线程的线程池 ExecutorService executor Executors.newSingleThreadExecutor(n); newSingleThreadExecutor是一个静态方法返回值是ExecutorService 2. 提交 Callable 任务 FutureString future executor.submit(new MyCallable()); submit 方法的内部以 AbstractExecutorService 的默认实现为例会做两件事 ① 将 Callable 包装成 FutureTask protected T RunnableFutureT newTaskFor(CallableT callable) { return new FutureTaskT(callable); } 这一步和你之前手动写的 FutureTaskString futureTask new FutureTask(myCallable); 一模一样——它生成一个既实现了 Runnable能被线程执行又实现了 Future能获取结果的对象。 ② 把 FutureTask 交给线程池执行 public Future? submit(Runnable task) { // 实际调用 execute 方法参数是 Runnable execute(task); return future; } execute 是 ThreadPoolExecutor 的核心方法它会 如果工作线程还没创建就创建一个新线程或者复用已有的空闲线程。 将 FutureTask作为 Runnable放入工作队列。 工作线程会从队列里不断取出任务调用它的 run() 方法。 所以本质上executor.submit 帮你完成了 “创建 FutureTask 启动线程执行” 这两个步骤。 3. 获取结果阻塞等待 System.out.println(future.get()); 此时 future 实际上就是那个被提交的 FutureTask 对象只是用 Future 接口引用它。 FutureTask.get() 的逻辑和你之前用的一样 如果任务还没执行完run() 还没把结果写进 outcome 字段当前线程这里是 main 线程就会阻塞。 阻塞通常通过 LockSupport.park() 实现并且会等待一个 signal 唤醒。 当工作线程执行完 FutureTask.run() 后 调用 callable.call() 拿到返回值或捕获异常。 将结果或异常保存到 outcome 字段。 调用 finishCompletion() 方法唤醒所有在 get() 上等待的线程。 被唤醒的 main 线程从 get() 返回拿到结果并打印。public class MyRunnable implements Runnable{ Override public void run() { System.out.println(Thread.currentThread().getName()...执行了); } }public class Test01 { public static void main(String[] args) { //创建线程池对象 ExecutorService es Executors.newFixedThreadPool(2); es.submit(new MyRunnable()); es.submit(new MyRunnable()); es.submit(new MyRunnable()); //es.shutdown();//关闭线程池对象 } }public class MyCallable implements CallableInteger { Override public Integer call() throws Exception { return 1; } }public class Test02 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService es Executors.newFixedThreadPool(3); FutureInteger f1 es.submit(new MyCallable()); FutureInteger f2 es.submit(new MyCallable()); FutureInteger f3 es.submit(new MyCallable()); FutureInteger f4 es.submit(new MyCallable()); FutureInteger f5 es.submit(new MyCallable()); System.out.println(f1.get()); System.out.println(f2.get()); System.out.println(f3.get()); System.out.println(f4.get()); System.out.println(f5.get()); } } 具体流程图如下阻塞队列(无界)线程池(3个工作线程)主线程阻塞队列(无界)线程池(3个工作线程)