1 package com.baozi.java2; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.FutureTask; 6 7 public class ThreadNew { 8 public static void main(String[] args){ 9 //3、创建callable接口实现类的对象 10 NewThread newThread= new NewThread(); 11 //4、将此callable接口实现类的对象作为参数传递到FutureTask类的构造器中创建出一个FutureTask的实现类 12 FutureTask futureTask = new FutureTask(newThread); 13 //5、将FutureTask类的对象作为参数传递给Thread类的构造器创建一个Thread对象然后调用start()方法启动该线程 14 new Thread(futureTask).start(); 15 try { 16 //6、可以通过futureTask.get()方法获取call()方法中的返回值 17 System.out.println(futureTask.get()); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } catch (ExecutionException e) { 21 e.printStackTrace(); 22 } 23 } 24 25 } 26 //1、创建一个类实现callable接口 27 class NewThread implements Callable<Integer> { 28 //2、实现该接口中的call()方法 29 @Override 30 public Integer call() { 31 int sum = 0; 32 for (int i = 1; i <= 100; i++) { 33 if (i % 2 == 0) { 34 sum += i; 35 } 36 } 37 return sum; 38 } 39 }
相比较Runnable接口,Callable接口的功能更加强大。
Future接口:
1 package com.baozi.java2; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.ThreadPoolExecutor; 6 7 public class ThreadPool { 8 public static void main(String[] args) { 9 //1、先创建一个线程池 10 ExecutorService service = Executors.newFixedThreadPool(10); 11 //3、为线程池中线程分配任务并执行 12 ThreadPoolExecutor service1=(ThreadPoolExecutor)service; 13 System.out.println(service.getClass()); 14 service.execute(new NumberThread1()); 15 service.execute(new NumberThread2()); 16 service.execute(new NumberThread3()); 17 //4、关闭线程池 18 service.shutdown(); 19 } 20 } 21 //2、创建要执行某种操作的线程 22 class NumberThread1 implements Runnable { 23 @Override 24 public void run() { 25 for (int i = 0; i <= 100; i++) { 26 if (i % 2 == 0) { 27 System.out.println(Thread.currentThread().getName() + ":" + i); 28 } 29 } 30 } 31 } 32 33 class NumberThread2 implements Runnable { 34 @Override 35 public void run() { 36 for (int i = 0; i <= 100; i++) { 37 if (i % 2 != 0) { 38 System.out.println(Thread.currentThread().getName() + ":" + i); 39 } 40 } 41 } 42 } 43 44 class NumberThread3 implements Runnable { 45 @Override 46 public void run() { 47 for (int i = 0; i <= 100; i++) { 48 System.out.println(Thread.currentThread().getName() + ":" + i); 49 } 50 } 51 }
传统的方法创建线程,当程序需要使用多线程的时候进行创建,用完之后就会立即销毁,如果频繁的进行这样的操作会消耗大量的系统资源,严重影响程序的性能。
1 public void execute(Runnable command) { 2 if (command == null) 3 throw new NullPointerException(); 4 /* 5 * Proceed in 3 steps: 6 * 7 * 1. If fewer than corePoolSize threads are running, try to 8 * start a new thread with the given command as its first 9 * task. The call to addWorker atomically checks runState and 10 * workerCount, and so prevents false alarms that would add 11 * threads when it shouldn‘t, by returning false. 12 * 如果正在运行的线程数小于corePoolSize,那么将调用addWorker 方法来创建一个新的线程,并将该任务作为新线程的第一个任务来执行。 13 当然,在创建线程之前会做原子性质的检查,如果条件不允许,则不创建线程来执行任务,并返回false. 14 15 * 2. If a task can be successfully queued, then we still need 16 * to double-check whether we should have added a thread 17 * (because existing ones died since last checking) or that 18 * the pool shut down since entry into this method. So we 19 * recheck state and if necessary roll back the enqueuing if 20 * stopped, or start a new thread if there are none. 21 * 如果一个任务成功进入阻塞队列,那么我们需要进行一个双重检查来确保是我们已经添加一个线程(因为存在着一些线程在上次检查后他已经死亡)或者 22 当我们进入该方法时,该线程池已经关闭。所以,我们将重新检查状态,线程池关闭的情况下则回滚入队列,线程池没有线程的情况则创建一个新的线程。 23 * 3. If we cannot queue task, then we try to add a new 24 * thread. If it fails, we know we are shut down or saturated 25 * and so reject the task. 26 如果任务无法入队列(队列满了),那么我们将尝试新开启一个线程(从corepoolsize到扩充到maximum),如果失败了,那么可以确定原因,要么是 27 线程池关闭了或者饱和了(达到maximum),所以我们执行拒绝策略。 28 29 */ 30 31 // 1.当前线程数量小于corePoolSize,则创建并启动线程。 32 int c = ctl.get(); 33 if (workerCountOf(c) < corePoolSize) { 34 if (addWorker(command, true)) 35 // 成功,则返回 36 37 return; 38 c = ctl.get(); 39 } 40 // 2.步骤1失败,则尝试进入阻塞队列, 41 if (isRunning(c) && workQueue.offer(command)) { 42 // 入队列成功,检查线程池状态,如果状态部署RUNNING而且remove成功,则拒绝任务 43 int recheck = ctl.get(); 44 if (! isRunning(recheck) && remove(command)) 45 reject(command); 46 // 如果当前worker数量为0,通过addWorker(null, false)创建一个线程,其任务为null 47 else if (workerCountOf(recheck) == 0) 48 addWorker(null, false); 49 } 50 // 3. 步骤1和2失败,则尝试将线程池的数量有corePoolSize扩充至maxPoolSize,如果失败,则拒绝任务 51 else if (!addWorker(command, false)) 52 reject(command); 53 }
ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:
原文:https://www.cnblogs.com/BaoZiY/p/10727180.html