文章目录
- Lambda
- Stream流
- 线程(池)
- IO
Lambda
使用前提
- 必须存在一个接口
- 接口中有且只有一个抽象方法
格式 : ( 形式参数 ) -> { 代码块 }
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
java">// 函数式接口:只有一个抽象方法的接口 加 @FunctionalInterface
@FunctionalInterface
public interface Calculator {public abstract int calculate(int a,int b);
}/*Lambda表达式:简化匿名内部类的代码语法:(参数列表) -> {方法体}参数列表:对应重写方法的参数列表方法体:对应重写方法的方法体->:箭头,分割参数列表和方法体注意:1. 如果参数列表为空,则可以省略小括号2. 如果参数列表只有一个参数,则可以省略小括号3. 如果方法体只有一行代码,则可以省略大括号和return关键字4. 如果方法体只有一行代码,并且是返回值,则可以省略大括号和return关键字
*/public class CalculatorTest {public static void main(String[] args) {//使用匿名内部类useCalculator(new Calculator() {@Overridepublic int calculate(int a, int b) {System.out.println(a - b);return a - b; // -10}});//使用Lambda表达式useCalculator((a, b) -> {System.out.println(a + b);return a + b; // 30});//简化Lambda表达式useCalculator((a, b) -> a * b); // 200}public static void useCalculator(Calculator calculator) {calculator.calculate(10, 20);}
}
Stream流
获取Stream流
- 创建一条流水线,并把数据放到流水线上准备进行操作
中间方法
- 流水线上的操作。
- 一次操作完毕之后,还可以继续进行其他操作
终结方法
- 一个Stream流只能有一个终结方法
- 是流水线上的最后一个操作
java">/*Stream 流1. Stream 流是 Java 8 的新特性,它允许我们对数据进行一系列的操作,如过滤、映射、排序等。2. Stream 流的使用可以让代码更加简洁、易读,同时提高代码的执行效率。3. Stream 流的操作是惰性的,即只有当需要结果时才会执行操作。4. Stream 流的操作是链式调用的,即可以在一个流上连续调用多个操作。5. Stream 流的操作是中间操作和终止操作,中间操作不会立即执行,而是返回一个新的流,终止操作会立即执行并返回结果。6. Stream 流的操作是并行执行的,即可以在多个线程上同时执行操作,提高代码的执行效率。
*/import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class StreamTest {public static void main(String[] args) {// 集合List<Integer> list = new ArrayList<>();// 添加元素Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 使用 stream 流list.stream().sorted().forEach(num -> System.out.println(num));list.stream().sorted((num1, num2) -> num2 - num1).forEach(num -> System.out.println(num));System.out.println("------------------------");List<String> list2 = new ArrayList<>();Collections.addAll(list2, "zuo", "shi", "xu", "hebut", "hebust");list2.stream().filter(str -> str.length() > 2).filter(str -> str.contains("he")).forEach(str -> System.out.println(str));}
}
线程(池)
线程的两种实现方法
- 继承Thread类
- 实现Runnable接口 (推荐!!!)
- 都需要重写run方法
java">// 继承Thread类
public class MyThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 500; i++) {System.out.println("hello" + i);}}
}// 实现Runnable接口
public class MyThread1 implements Runnable {@Overridepublic void run() {for (int i = 500; i < 1000; i++) {System.out.println("world" + i);}}
}// main方法
public class ThreadTest {public static void main(String[] args) {System.out.println("main 方法开始了 ...");// 方式1 继承 Thread类// 创建任务类对象MyThread t1 = new MyThread();// 启动线程t1.start();// 方式2 实现 Runnable接口// 创建任务类对象MyThread1 t2 = new MyThread1();// 创建线程对象Thread t3 = new Thread(t2);// 启动线程t3.start();for (int i = 1000; i < 1500; i++) {System.out.println("main 方法执行了 " + i);}}
}
线程安全问题 (访问共享数据的问题)
1. 同步代码块
synchronized(锁对象){}
锁对象 可以是任意对象
2. 同步方法
把访问了共享数据的代码抽取出来,放到一个方法中
使用synchronized修饰这个方法
锁对象 就是this
3. 静态同步方法
把访问了共享数据的代码抽取出来,放到一个静态方法中
使用synchronized修饰这个方法
锁对象 就是 类名.class
4. Lock
new ReentrantLock();
lock.lock(); // 上锁
lock.unlock(); // 开锁
java">import java.util.concurrent.locks.ReentrantLock;public class Ticket implements Runnable {private int ticket = 100; //票数// Lock 推荐ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true) {try {lock.lock();if (ticket <= 0) {break;}if (ticket > 0) {Thread.sleep(100); // 模拟网络延迟System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");}ticket--;} catch (Exception e) {e.printStackTrace();} finally {lock.unlock(); // 永远会执行 不管上面是否有异常 跳出 while也会执行}}}// // 自定义锁对象
// Object lock = new Object();
//
// @Override
// public void run() {
// while (true) {
// // 同步代码块
// synchronized (lock) {
// if (ticket <= 0) {
// break;
// }
// if (ticket > 0) {
// System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
// }
// ticket--;
// }
// }
// }// @Override
// public void run() {
// while (true) {
// if (method()){
// break;
// }
// }
// }
//
// // 同步方法
// private synchronized boolean method(){
// if (ticket <= 0) {
// return true;
// }
// if (ticket > 0) {
// System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
// }
// ticket--;
// return false;
// }
}// main 方法
public class TicketTest {public static void main(String[] args) {// 任务对象Ticket ticket = new Ticket();// 线程对象 + 线程起名Thread t1 = new Thread(ticket,"窗口1");Thread t2 = new Thread(ticket,"窗口2");Thread t3 = new Thread(ticket,"窗口3");// 启动线程t1.start();t2.start();t3.start();}
}
生产者消费者问题
- 同步锁(synchronized) 解决线程访问共享数据的问题
java">// 共享数据
public class Resource {// 不能加 private 类名.属性名 访问不到static int num = 0; // 一开始桌子上没食物static final Object lock = new Object(); // 锁对象
}// 生产者
public class Cooker implements Runnable {@Overridepublic void run() {while (true) {synchronized (Resource.lock) {if (Resource.num == 0) {System.out.println(Thread.currentThread().getName() + "开始做饭");Resource.num = 1;Resource.lock.notify(); // 唤醒阻塞进程} else {try {System.out.println(Thread.currentThread().getName() + "阻塞");Resource.lock.wait(); // 阻塞进程} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}
}// 消费者
public class Consumer implements Runnable {@Overridepublic void run() {while (true) {synchronized (Resource.lock) {if (Resource.num == 1) {System.out.println(Thread.currentThread().getName() + "开始吃饭");Resource.num = 0;Resource.lock.notify(); // 唤醒阻塞进程} else {try {System.out.println(Thread.currentThread().getName() + "阻塞");Resource.lock.wait(); // 阻塞进程} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}
}// main 方法
public class Test {public static void main(String[] args) {// 任务对象Cooker cooker = new Cooker();Consumer consumer = new Consumer();// 线程对象Thread t1 = new Thread(cooker, "厨师");Thread t2 = new Thread(consumer, "消费者");// 启动线程t1.start();t2.start();}
}
线程池
- 通过Executors创建线程池对象
java">import java.util.concurrent.*;public class CallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {// 线程池对象 Executors + sExecutorService pool = Executors.newFixedThreadPool(3);// 创建 Callable 类型的线程Callable<Integer> task = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 10; i++) {sum += i;}return sum;}};// 执行 Callable 类型的线程Future<Integer> future = pool.submit(task);System.out.println("Callable线程执行完毕,结果为:" + future.get());}
}
IO
复制文件(读文件 + 写文件)三种方法
- 一个字节一个字节读
- 每次读写指定大小的字节
- 采用缓冲区读取(大小自定义) 推荐!!!
java">// 方法一
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyFile {public static void main(String[] args) {// 创建字节流对象FileInputStream fileInputStream = null;FileOutputStream fileOutputStream = null;long beginTime = 0;long endTime = 0;try {beginTime = System.currentTimeMillis();// 读字节流fileInputStream = new FileInputStream("day06/file/nuannuan.jpeg");// 写字节流fileOutputStream = new FileOutputStream("day06/file/nuanuan2.jpeg", true);// 读文件 写文件int data = 0;while ((data = fileInputStream.read()) != -1) {fileOutputStream.write(data);}} catch (IOException e) {e.printStackTrace();} finally {// 释放资源 永远会执行 finally里的东西try {if (fileInputStream != null) {fileInputStream.close();}if (fileOutputStream != null) {fileOutputStream.close();}endTime = System.currentTimeMillis();System.out.println("耗时:" + (endTime - beginTime) + "ms"); // 9142ms} catch (IOException e) {e.printStackTrace();}}}
}// 方法二
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyFileBytes {public static void main(String[] args) {//1.创建输入输出流对象FileInputStream fis = null;FileOutputStream fos = null;long beginTime = 0;long endTime = 0;try {beginTime = System.currentTimeMillis();fis = new FileInputStream("day06/file/nuannuan.jpeg");fos = new FileOutputStream("day06/file/nuannuan1.jpeg");//2.读写数据byte[] bytes = new byte[1024]; // 每次读取1Kint len;while ((len = fis.read(bytes)) != -1) {fos.write(bytes, 0, len); // 每次写读取到的长度}endTime = System.currentTimeMillis();} catch (IOException e) {throw new RuntimeException(e);} finally {//3.关闭资源try {if (fis != null) {fis.close();}if (fos != null) {fos.close();}System.out.println("耗时:" + (endTime - beginTime) + "ms"); // 17ms} catch (IOException e) {e.printStackTrace();}}}
}// 方法三
import java.io.*;public class CopyFileBuffer {public static void main(String[] args) {// 1. 创建源和目标对象BufferedInputStream bis = null;BufferedOutputStream bos = null;long startTime = 0;long endTime = 0;// 2.读写文件try {startTime = System.currentTimeMillis();bis = new BufferedInputStream(new FileInputStream("day06/file/nuannuan.jpeg"), 1024 * 80);bos = new BufferedOutputStream(new FileOutputStream("day06/file/nuannuan1.jpeg"), 1024 * 80);int len = 0;while ((len = bis.read()) != -1) {bos.write(len);}} catch (IOException e) {e.printStackTrace();} finally {// 3. 释放资源try {if (bis != null) {bis.close();}if (bos != null) {bos.close();}endTime = System.currentTimeMillis();System.out.println("耗时:" + (endTime - startTime) + "ms"); //152ms} catch (Exception e) {e.printStackTrace();}}}
}
字符流 = 字节流 + 编码表读文件