/** * Future模式有点类似于商品订单。比如在网购时,当看重某一件商品时,就可以提交订单, * 当订单处理完成后,在家里等待商品送货上门即可。或者说更形象的我们发送Ajax请求的时候, * 页面是异步的进行后台处理,用户无需一直等待请求的结果,可以继续浏览或操作其他内容。 */ public class Main { public static void main(String[] args) { FutureClient fc = new FutureClient(); Data data = fc.request("请求参数"); System.out.println("请求发送成功!"); System.out.println("做其他的事情。。。"); String result = data.getRequest(); System.out.println(result); }
}
public class FutureClient { public Data request(final String queryStr){ /** * 1. 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他 * 请求已经接收到,可以做其他的事情。 */ final FutureData futureData = new FutureData(); /** * 2. 启动一个新的线程,去加载真实的数据,传递给这个代理对象 */ new Thread(new Runnable() { @Override public void run() { /** * 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象 */ RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); return futureData; } }
public interface Data {
String getRequest();
}
public class RealData implements Data { private String result; public RealData(String queryStr){ System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作。。"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("操作完毕,获取结果"); result = "查询结果"; } @Override public String getRequest() { return result; } }
public class FutureData implements Data { private RealData realData; private boolean isReady = false; public synchronized void setRealData(RealData realData){ //如果已经装载完毕了,就直接返回 if(isReady){ return; } //如果没装载,进行装载真实数据 this.realData = realData; isReady = true; //进行通知 notify(); } @Override public synchronized String getRequest() { //如果没装载好,程序就一直处于阻塞状态 while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //装载好直接获取数据即可 return this.realData.getRequest(); } }
import java.util.Random; /** * Master-Worker模式是常用的并行计算模式。它的核心思想是系统由两类进程协作工作: * Master进程和Worker进程。Master负责接收和分配任务,Worker负责处理子任务。当各个 * Worker子进程处理完成后,会将结果返回给Master,由Master做归纳和总结。其好处是能 * 将一个大任务分解成若干个小任务,并行执行,从而提高系统的吞吐量。 */ public class Main { public static void main(String[] args) { Master master = new Master(new Worker(),20); Random r = new Random(); for (int i = 1; i <= 100 ; i++){ Task t = new Task(); t.setId(i); t.setPrice(r.nextInt(1000)); master.submit(t); } master.execute(); long start = System.currentTimeMillis(); while(true){ if(master.isComplete()){ long end = System.currentTimeMillis() - start; int priceResult = master.getResult(); System.out.println("最终结果:" + priceResult + ",执行时间:" + end); break; } } } }
public class Task { private int id; private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; public class Master { /** * 1.有一个盛放任务的容器 * 我们不需要阻塞。支持高并发 */ private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>(); /** * 2.需要有一个盛放worker的集合 */ private HashMap<String,Thread> workers = new HashMap<String, Thread>(); /** * 3.需要有一个盛放每一个worker执行任务的结果集合 */ private ConcurrentHashMap<String,Object> resultMap = new ConcurrentHashMap<String,Object>(); /** * 4.构造方法 */ public Master(Worker worker,int workerCount){ worker.setWorkQueue(this.workQueue); worker.setResultMap(this.resultMap); for (int i = 0;i < workerCount ; i++){ this.workers.put(Integer.toString(i),new Thread(worker)); } } /** * 5.需要一个提交任务的方法 */ public void submit(Task task){ this.workQueue.add(task); } /** * 6.需要有一个执行方法,启动所有的worker方法去执行任务 */ public void execute(){ for (Map.Entry<String,Thread> ms : workers.entrySet()){ ms.getValue().start(); } } /** * 7.判断是否运行结束的方法 */ public boolean isComplete(){ for (Map.Entry<String,Thread> me : workers.entrySet()){ if(me.getValue().getState() != Thread.State.TERMINATED){ return false; } } return true; } /** * 8.计算结果方法 */ public int getResult(){ int priceResult = 0; for (Map.Entry<String,Object> me : resultMap.entrySet()){ priceResult += (Integer)me.getValue(); } return priceResult; } }
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; public class Worker implements Runnable { private ConcurrentLinkedQueue<Task> workQueue; private ConcurrentHashMap<String,Object> resultMap; public void setWorkQueue(ConcurrentLinkedQueue<Task> workQueue) { this.workQueue = workQueue; } public void setResultMap(ConcurrentHashMap<String, Object> resultMap) { this.resultMap = resultMap; } @Override public void run() { while(true){ Task input = this.workQueue.poll(); if (input == null) break; Object output = handle(input); this.resultMap.put(Integer.toString(input.getId()),output); } } private Object handle(Task input){ Object output = null; try{ Thread.sleep(500); output = input.getPrice(); }catch (InterruptedException ex){ ex.printStackTrace(); } return output; } }
import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingDeque; /** * 生产者和消费者也是一个非常经典的多线程模式,我们在实际开发中应用非常广泛的思想 * 理念。在生产-消费模式中:通常由两类线程,及若干个生产者的线程和若干个消费者的线 * 程。生产者线程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务,在生 * 产者和消费者之间通过共享内存缓冲区进行通信 * */ public class Main { public static void main(String[] args) { /** * 内存缓冲区 */ BlockingQueue<Data> queue = new LinkedBlockingDeque<Data>(10); //生产者 Provider p1 = new Provider(queue); Provider p2 = new Provider(queue); Provider p3 = new Provider(queue); //消费者 Consumer c1 = new Consumer(queue); Consumer c2 = new Consumer(queue); Consumer c3 = new Consumer(queue); /** * 创建线程池运行,这是一个缓存的线程池,可以创建无穷大的线程,没有任务的时候 * 不创建线程。空闲线程存活时间为60s(默认值) */ ExecutorService cachePool = Executors.newCachedThreadPool(); cachePool.execute(p1); cachePool.execute(p2); cachePool.execute(p3); cachePool.execute(c1); cachePool.execute(c2); cachePool.execute(c3); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } p1.stop(); p2.stop(); p3.stop(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // cachePool.shutdown(); // cachePool.shutdownNow(); } }
public final class Data { private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Data(String id,String name){ this.id = id; this.name = name; } @Override public String toString() { return "{id:" + id + ", name:" + name + "}"; } }
import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class Provider implements Runnable{ //共享缓存区 private BlockingQueue<Data> queue; /** * 多线程间是否启动变量,有强制从住内存中刷新的功能,即时返回线程的状态 */ private volatile boolean isRunning = true; //id生成器 private static AtomicInteger count = new AtomicInteger(); //随机对象 private static Random r = new Random(); public Provider(BlockingQueue queue){ this.queue = queue; } @Override public void run() { while(isRunning){ try { Thread.sleep(r.nextInt(1000)); int id = count.incrementAndGet(); Data data = new Data(Integer.toString(id),"数据" + id); System.out.println("当前线程:" + Thread.currentThread().getState() + ",获取了数据,id为:" + id + "进行装载到公共缓冲区中..."); if (!this.queue.offer(data,2,TimeUnit.SECONDS)){ System.out.println("提交缓冲区数据失败..."); //do something ... 比如重新提交 } } catch (InterruptedException e) { e.printStackTrace(); } } } public void stop(){ this.isRunning = false; } }
import java.util.Random; import java.util.concurrent.BlockingQueue; public class Consumer implements Runnable { private BlockingQueue<Data> queue; public Consumer(BlockingQueue queue){ this.queue = queue; } private static Random r = new Random(); @Override public void run() { while(true){ try { Data data = this.queue.take(); Thread.sleep(r.nextInt(1000)); System.out.println("当前消费线程:" + Thread.currentThread().getName() + ",消费成功,消费数据为id:" + data.getId()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 为了更好地控制多线程,JDK提供了一套线程框架Executor,帮助开发人员有效地进行线程控 * 制。他们都在java.util.concurrent包中,是JDK并发包的核心。其中有一个比较重要的类: * Executors,它扮演这线程工厂的角色,我们通过Executors可以创建特定功能的线程池。 * * Executors创建线程池方法: * * newFinedThreadPool()方法,该方法返回一个固定数量的线程池,该方法的线程数始终不变, * 当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列 * 中等待有空闲的线程去执行。 * * newSingleThreadExecutor()方法,创建一个线程的线程池,若空闲则执行,若没有空闲线 * 程则暂缓在任务队列中。 * * newCachedThreadPool()方法,返回一个可根据实际情况调整线程个数的线程池,不限制最大 * 线程数量。若有任务,则创建线程,若无任务则不创建线程,如果没有任务则线程在60s后 * 自动回收(空闲时间60s)。 * * newScheduledThreadPool()方法,该方法返回一个SchededExecutorService对象,但该线程 * 池可以指定线程的数量。 * * 若Executors工厂类无法满足我们的需求,可以自己去创建自定义的线程池,其实Executors * 工厂类里面的创建线程方法其内部实现均是用了ThreadPoolExecutor这个类,这个类可以自 * 定义线程。构造方法如下: * public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, * TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory, * RejectedExecutionHandler handler){...} */ public class UseExcutors { public static void main(String[] args) { ExecutorService pool1 = Executors.newScheduledThreadPool(10); ExecutorService pool2 = Executors.newFixedThreadPool(10); ExecutorService pool3 = Executors.newSingleThreadExecutor(); ExecutorService pool4 = Executors.newCachedThreadPool(); } }