Day17学习Java
仓储模型
需求:
生产者线程不断的生产面包放入仓库
消费者线程不断的从仓库中取出面包
做到先生产的面包先卖出
分析:
生产者线程、消费者线程、面包类、仓库类
先生产的面包先卖出 – 队列模式(LinkedList)
场景:一个生产者,一个消费者
public static void main(String[] args) {Store store = new Store();Producer p = new Producer(store);Consumer c = new Consumer(store);p.start();c.start();
}
public class Store {这里赋予仓库最大的限度为20private static final int MAX_INIT_CAPACITY = 20;private int curCapacity;//初始容量private int maxCapacity;//最大容量private LinkedList<Cake> list;public Store() {this(MAX_INIT_CAPACITY);}public Store(int maxCapacity) {this.maxCapacity = maxCapacity;list = new LinkedList<>();}//入库 - 生产者线程不断的调用public synchronized void push(Cake cake){if(curCapacity >= maxCapacity){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}curCapacity++;list.add(cake);System.out.println("入库,当前容量为:" + curCapacity);notify();}//出库 - 消费者线程不断的调用public synchronized Cake pop(){if(curCapacity <= 0){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}curCapacity--;Cake cake = list.removeFirst();System.out.println("出库,当前容量为:" + curCapacity + " -- " + cake);notify();return cake;}
}
public class Cake {private String brand;//品牌private String datetime;//日期时间public Cake(String brand, String datetime) {this.brand = brand;this.datetime = datetime;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getDatetime() {return datetime;}public void setDatetime(String datetime) {this.datetime = datetime;}@Overridepublic String toString() {return brand + " -- " + datetime;}
}
public class Producer extends Thread{//生产者继承Threadprivate Store store;//定义了一个名为 store 的变量,该变量是一个 Store 类型的对象,并且是私有的。public Producer(Store store) {this.store = store;}@Overridepublic void run() {while(true){Cake cake = new Cake("好利来", LocalDateTime.now().toString());store.push(cake);}}
}
public class Consumer extends Thread{//消费者继承Threadprivate Store store;public Consumer(Store store) {this.store = store;}@Overridepublic void run() {while(true){store.pop();}}
}
场景:多个生产者,多个消费者
public static void main(String[] args) {Store store = new Store();Producer p1 = new Producer(store); Producer p2 = new Producer(store);Consumer c1 = new Consumer(store);Consumer c2 = new Consumer(store);p1.start();p2.start();c1.start();c2.start();
}
public class Store {private static final int MAX_INIT_CAPACITY = 20;private int curCapacity;private int maxCapacity;private LinkedList<Cake> list;public Store() {this(MAX_INIT_CAPACITY);}public Store(int maxCapacity) {this.maxCapacity = maxCapacity;list = new LinkedList<>();}//入库 - 生产者线程不断的调用public synchronized void push(Cake cake){while(curCapacity >= maxCapacity){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}curCapacity++;list.add(cake);System.out.println("入库,当前容量为:" + curCapacity);notifyAll();}//出库 - 消费者线程不断的调用public synchronized Cake pop(){while(curCapacity <= 0){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}curCapacity--;Cake cake = list.removeFirst();System.out.println("出库,当前容量为:" + curCapacity + " -- " + cake);notifyAll();return cake;}
}
public class Cake {private String brand;private String datetime;public Cake(String brand, String datetime) {this.brand = brand;this.datetime = datetime;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getDatetime() {return datetime;}public void setDatetime(String datetime) {this.datetime = datetime;}@Overridepublic String toString() {return brand + " -- " + datetime;}
}
public class Producer extends Thread{private Store store;public Producer(Store store) {this.store = store;}@Overridepublic void run() {while(true){Cake cake = new Cake("好利来", LocalDateTime.now().toString());store.push(cake);}}
}
public class Consumer extends Thread{private Store store;public Consumer(Store store) {this.store = store;}@Overridepublic void run() {while(true){store.pop();}}
}
使用Java自带的线程池
Executors:线程池的工具类
ExecutorService:线程池的接口
public static void main(String[] args) {//创建单个线程的线程池ExecutorService pool = Executors.newSingleThreadExecutor();for (int i = 1; i <= 100; i++) {//提交任务pool.execute(new Task(i));}//关闭线程池pool.shutdown();
}
public static void main(String[] args) {//创建指定线程个数的线程池ExecutorService pool = Executors.newFixedThreadPool(3);for (int i = 1; i <= 100; i++) {//提交任务pool.execute(new Task(i));}//关闭线程池pool.shutdown();
}
public static void main(String[] args) {//创建可缓存的线程池(该线程池里有0个线程,任务等待就会创建新的线程去服务他,60秒没有工作的线程认为是闲置线程会被回收)ExecutorService pool = Executors.newCachedThreadPool();for (int i = 1; i <= 100; i++) {//提交任务pool.execute(new Task(i));}//关闭线程池pool.shutdown();
}
public static void main(String[] args) throws InterruptedException {//创建延迟任务的线程池ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);//设置延迟时间pool.awaitTermination(5, TimeUnit.SECONDS);for (int i = 1; i <= 100; i++) {//提交任务pool.execute(new Task(i));}//关闭线程池pool.shutdown();
}
线程
需求:计算任务,一个包含了2万个整数的数组,分拆了多个线程来进行并行计算,最后汇总出计算的结果。
注意:
1.使用带返回值的任务类方式解决该需求
2.带有返回值的任务类和线程池联合使用
public static void main(String[] args) throws InterruptedException, ExecutionException {//创建数组,并初始化数据int[] arr = new int[20000];for (int i = 0; i < arr.length; i++) {arr[i] = i+1;}//创建线程池FastThreadPool pool = new FastThreadPool(4, 4, 60, TimeUnit.SECONDS, 20);//创建任务Task task1 = new Task(arr, 0, 5000);Task task2 = new Task(arr, 5000, 10000);Task task3 = new Task(arr, 10000, 15000);Task task4 = new Task(arr, 15000, 20000);//提交任务,并返回Future对象(带有返回值的任务类返回的数据就存在Future对象)Future<Integer> f1 = pool.submit(task1);Future<Integer> f2 = pool.submit(task2);Future<Integer> f3 = pool.submit(task3);Future<Integer> f4 = pool.submit(task4);//合并线程结果System.out.println(f1.get() + f2.get() + f3.get() + f4.get());pool.shutdown();
}
public class Task implements Callable<Integer>{private int[] arr;private int startIndex;private int endIndex;public Task(int[] arr, int startIndex, int endIndex) {this.arr = arr;this.startIndex = startIndex;this.endIndex = endIndex;}@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = startIndex; i < endIndex; i++) {sum += arr[i];}return sum;}
}
自定义线程池
public static void main(String[] args) {ThreadPoolExecutor pool = new ThreadPoolExecutor(5, //核心线程数20, //最大线程数60, //闲置时间TimeUnit.SECONDS,//时间单位 new ArrayBlockingQueue<>(20),//任务队列 - 有界队列 new ThreadFactory() {//自定义线程工厂(可以给线程定义名称和优先级...)private int count = 1;@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "线程" + count);t.setPriority(Thread.MAX_PRIORITY);count++;return t;}}, new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println("任务被拒绝了...");}});//闲置时间到后,核心线程和普通线程都会被销毁//不设置该方法,闲置时间到后只会销毁普通线程//经验:不用该方法,因为把所有的线程都销毁,就没有线程复用率这个概念了//pool.allowCoreThreadTimeOut(true);for (int i = 1; i <= 100; i++) {//提交任务pool.execute(new Task(i));}//关闭线程池pool.shutdown();}
public class Task implements Runnable{private int num;public Task(int num) {this.num = num;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "线程被执行了任务" + num);}
}