面向函数式编程
程序员文章站
2022-05-08 09:16:05
...
面向函数式编程@FunctionalInterface
-
1:面向函数式编程四大点:
/** * 面向函数式编程 * 1 拷贝方法的后面小括号(有参数就带参数),写死右箭头,落地大括号(内写方法的实现)---lambda表达式 * 2 本质就是接口中只有一个方法时,jdk8 会自动在接口上默认@FunctionalInterface * 3 default 就是在接口定义方法上,实现了方法 可以允许存在多个default方法 * 4 static 静态代码块,可以运行存在多个default方法` */
eg:
public static void main(String[] args) {
/* 匿名内部类方式调用无参数无返回值的foo接口的方法·
Foo foo1=new Foo() {
@Override
public void sayhello() {
System.out.println("我要sayhello--匿名内部类方式调用无参数无返回值的foo接口的方法");
}
};
foo1.sayhello();
*/
/* 使用lambda表达式调用无参数无返回值的foo接口的方法
使用:拷贝小括号,写死右箭头,落地大括号+表达式
Foo foo2=()->{System.out.println("我要sayhello--使用lambda表达式调用无参数无返回值的foo接口的方法");};
foo2.sayhello();
*/
// 使用lambda表达式调用有参数有返回值的foo接口的方法
Foo foo3=(int x,int y)->{System.out.println(" 使用lambda表达式调用有参数有返回值的foo接口的方法:");return x+y;};
System.out.println(foo3.add(3, 4));
// 使用静态代码块或者default的接口方法时,只用接口方法. 就可以了
System.out.println(Foo.div(10, 5));
}
-
2:Collection 和Collections
- Collection 是一个集合接口,提供了对集合对象进行基本操作的通用接口方法
- Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
-
3:ArrayList的使用错误实例
-
出错的代码及其异常: //异常: java.util.ConcurrentModificationException
//异常 java.util.ConcurrentModificationException public static void main(String[] args) { //使用了Arraylist是一种线程不安全的方法 List<Object> list = new ArrayList<>(); for (int i=0;i<30;i++){ new Thread(()->{ //使用uuid来随机生成,然后转换为字符串,并且将字符串分割取出0-8位 list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } }
解决异常方法
List<Object> list = new ArrayList<>(); (线程不安全)改为 (1)List<Object> list = new Vector<>(); 本质add方法使用了synchronized,进行了上锁,不建议 (线程安全) (2)List<Object> list = Collections.synchronizedList(new ArrayList<>()); 使用了Collections工具类 (3)List<Object> list =new CopyOnWriteArrayList<>(); 具有内存占用问题,并且有数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。在开辟一个length+1的数组,并且把最新的数据放入数组的最后,并且将对老数组的索引转换到新数组上 /** copyonurite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器object[]添加,而是先将当前容器object[]进行copy,复制出一个新的容器bject[] newElements,然后新的容器object[] newElements里添加元素,添加完元素之后,再将原容器的引用指向新的容器setArray(newElements);。这样做的好处是可以为copyonurite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素,所以copyonwrite也是一种读写分离的思想,读和写不同的容器 */
-
八锁情况(自定义的)
* 1 标准访问。俩个同步代码块,一部手机,俩个用户,先发短信还是邮件 -------邮件 * 2 暂停3秒再发邮件,1部手机,俩个用户,先发短信还是邮件 -------邮件 * 3 一个普通方法,一个同步代码块,1部手机,俩个用户,先发普通方法还是邮件 -------普通方法 * 4 2部手机,先发短信还是邮件 -------短信 * 5 俩个静态代码块,一部手机,俩个用户,先发短信还是邮件 -------邮件 * 6 俩个静态代码块,2部手机,俩个用户,先发短信还是邮件 -------邮件 * 7 一个静态代码块,一个同步代码块,1部手机,俩个用户,先发普通方法还是邮件 -------短信 * 8 一个静态代码块,一个同步代码块,2部手机,俩个用户,先发普通方法还是邮件 -------短信
详情
synchronize锁的是对象,创建出来的对象 eg:phone1,phone2 static synchronize 锁的是创建这个对象的模板,为整个Class类 eg:Phone 同步方法和普通方法,等于俩道门,俩把锁,不影响
-
多线程的相互调用资源类,防止过多调用,过着过少调用(生产与消费)
* 题目:现在两个线程,可以操作初始值为零的一个变量, * -实现一个线程对该变量加,一个线程对该变量减, * 实现交替,来10轮,变量初始值为零。
-
解决方案:
- 1 高聚低合前提下,线程操作资源类
- 2 判断/干活/通知
- 3 防止虚假唤醒,所以每次苏醒都得判断(用while进行判断,一旦不该苏醒的时候苏醒,就沉入睡眠)
eg: //空调类--资源类 public class Aircondition { // 度数 private int number=0; // 空调-1度 public synchronized void decrement() throws Exception{ // 判断,防止虚假唤醒,所以每次苏醒都得判断 while(number!=1){ this.wait(); } // 干活 number--; System.out.println(Thread.currentThread().getName()+"当前的number-1,number=:"+number); // 通知(唤醒其他线程) this.notify(); } // 空调+1度 public synchronized void increment() throws Exception{ //判断,防止虚假唤醒,所以每次苏醒都得判断 while(number!=0){ this.wait(); } //干活 number++; System.out.println(Thread.currentThread().getName()+"当前的number+1,number=:"+number); //通知(唤醒其他线程) this.notify(); } }
-
遇到多个线程按照固定顺序来进行运行,例如A->B->C->A····
-
应当在资源类上精准配置钥匙,即标示位
public class ShareData { private Lock lock=new ReentrantLock(); private Condition c1 = lock.newCondition(); private Condition c2 = lock.newCondition(); private Condition c3 = lock.newCondition(); private int number=1;//A:1 B:2 C:3 public void doA() throws InterruptedException { lock.lock(); try{ // 判断 while(number!=1){ c1.await(); } // 执行 System.out.println("我是A,我打印了5次"); // 通知 number=2; //唤醒第二个线程 c2.signal(); }catch(Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void doB() throws InterruptedException { lock.lock(); try{ // 判断 while(number!=2){ c2.await(); } // 执行 System.out.println("我是B,我打印了10次"); // 通知 number=3; c3.signal(); }catch(Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void doC() throws InterruptedException { lock.lock(); try{ // 判断 while(number!=3){ c3.await(); } // 执行 System.out.println("我是C,我打印了15次"); // 通知 number=1; c1.signal(); }catch(Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } }
配置多把钥匙,来上锁 private Condition c1 = lock.newCondition(); private Condition c2 = lock.newCondition(); private Condition c3 = lock.newCondition();
-
-
可获取函数的返回值,(异步操作)
主线程 public class CallableDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask(new MyThread()); // 进入了方法 new Thread(futureTask,"A").start(); // 获取任务执行结果,任务结束之前会阻塞 Integer result = futureTask.get(); System.out.println(result); } }
资源类,需要继承Callable<>接口 public class MyThread implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("********call in back on"); return 1024; } }
未完待续----------------
-