zoukankan      html  css  js  c++  java
  • Java | Stream流、泛型、多线程 | 整理自用

     

    1、lambda 表达式

    lambda 的延迟执行

    可以对程序进行优化,尤其是使用 if {} else {} 条件判断,先判断条件是否成立,再传入计算好的参数。

     

    functionName( paramters, () -> { } );

     

    2、stream 流式思想

    stream 是jdk8之后出现的语法

    拼接流式模型:建立一个生产线,按照生产线来生产商品

     

     

     经过了过滤、映射、跳过、计数等多步操作,集合元素的处理方案

    filter、map、skip,得益于lambda的延迟执行特性。

    (1) 获取流  

    数据源流的来源:集合、数组

    java.util.stream.Stream<T> 

    // 所有的Collention 集合 (   list, map, set..   )都可以通过stream默认方法获取流
    ArrayList<String> arrStr = new ArrayList();		
    stream<String> stream1 = arrStr.stream();
    
    // Stream接口的静态方法 of 可以获取数组对应的流
    Stream<Integer> Stream2 = Stream.of(1, 4, 3, 5, 5);
    // Stream 流只能使用一次,使用完之后就直接关闭了。即
    Stream<String> stream3 = Stream.of("1", "2", "9", "4");
    stream3.forEach((String str)-> { System.out.println(str); }); // 再重新打印一次,输出异常 stream3.forEach((String str)-> { System.out.println(str); });

     

    (2)取用前几个:limit  如果当前长度大于参数进行截取,否则不截取。limit 是一个延迟方法,返回的是一个新的流

    Stream<String> stream4 = stream3.limit(2);
    stream4.forEach( str -> System.out.println(str) );

     

    (3)跳过前几个:skip  与 limit 相反

     

     

    (4)流拼接: concat

     

     java 泛型

     java泛型不允许静态化,类中含有 static 会报错:

    // 分类:
    // 1、泛型类
    public class 类名<T> {
    
    }
    
    // 2、泛型接口
    public interface Generator<T> {
    
    }
    
    // 3、泛型方法

     

    类型通配符 ?

    区别:
    <? extends T> 该通配符所代表的类型是T类型的子类

    <? super T> 该通配符所代表的类型是T类型的父类

    反射提供的是runtime阶段获取类的class 实例、方法、属性、注解, 并且能够调用勒的方法的途径。

     

    java 多线程

    PS:查阅了相关资料和视频,这种类似于计算机内核原理的知识,建议翻阅教科书,了解一下什么是堆,栈,缓冲区等计算机专属词汇,网上很多人讲的不严谨,如果有人想深入大体了解内部机制,强烈安利这个教程 计算机系统基础,有好几季,课程比较长,虽然比较难

    并行:指两个或多个事件在同一时刻运行(同时运行)。

    并发:指两个或多个事件在同一个时间间隔内发生。

     

    线程与进程两者的关系图,推荐看这个图,比较严谨:

    https://blog.csdn.net/weixin_41490593/article/details/90704559

     

    多线程编程: 

    Java中线程有四种创建方式:

    l  继承Thread类

    l  实现Runnable接口

    l  实现Callable接口

    l  线程池

    前三种方法相应的资料很多,这里仅仅粗略赘述线程池:

    /*
    java.util.concurrent.ExecutorService  线程池接口
    
    线程池:容器 -- > 集合框架( ArrayList, HashSet, LinkedList<Thread>, HashMap )
    
    接口: 
    
    static ExecutorService newFixedThreadPool(int nThreads)  创建一个可重用固定线程数的线程池
    
    ExecutorService 接口,返回的是ExecutorService接口的实现类对象,可用ExecutorService接口接收(面向接口编程)
    
    submit() 执行线程 线程池会一直开启,使用完了线程,会自动吧线程归还给线程池,线程可以继续执行。
    
    shutdown() 关闭执行, 如果已经执行了此方法,如果重新 使用 submit 方法, 会报错 。
    
    
    
    线程池的使用步骤:
    
    1、使用线程池的工厂类 Executors 里面提供的 newFixedThreadPool 生产一个指定线程池数量的线程池
    
    2、创建一个类,实现 Runnable 接口,重写 run 方法,设置线程任务
    
    3、调用ExecutorService 中的方法 submit ,传递线程任务(实现类), 开启线程, 执行 run 方法
    
    4、调用ExecutorService 中的方法 shutdown ,销毁线程池
    
    */
    进程间协作:

    wait : 是object 类中的一个方法,当前线程释放自己的锁标记,让出CPU资源,当前的线程进入到等待队列中

    notify: 是object 类中的一个方法,唤醒等待队列中的一个进程,使这个线程进入锁池

    notifyAll : 唤醒等待队列中的等待当前对象的所有线程,并使这些线程进入锁池

    java线程同步机制:

    锁,通俗地讲就是告诉其他的线程,这里的鱼塘我承包了,等我解锁你再用

    同步锁: 多个线程看到的锁, 需要是同一把锁。

    静态方法:同步锁就是类锁,  当前类.class  属性  --> class 文件对象,这一点涉及到 java反射,静态方法优先于对象。

    非静态方法: 同步锁 是 this,this 是在创建对象之后产生的。

    Runnable r = () -> {
    	while(TicketCenter.restCount > 0 ) {
    //				synchronized ("") {
    		synchronized (Generic.class) {
    			if (TicketCenter.restCount <= 0) {
    				return ;
    			}
    			System.out.println("当前运行的进程 :  " + Thread.currentThread().getName() + "  " + --Center.restCount);
    		}
    	}
    };
    
    
    Thread t1 = new Thread(r, "thread - 1");
    Thread t2 = new Thread(r, "thread - 2");
    Thread t3 = new Thread(r, "thread - 3");
    Thread t4 = new Thread(r, "thread - 4");
    
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    class Center {
        public static int restCount = 100;
    
    }
    
    // 如果一个方法需要执行同步操作,直接加入 synchronize 关键字
    

     

    // 同步方法
    private synchronized static void funControl() {
    //		synchronized (Generic.class) {
    		if (TicketCenter.restCount <= 0) {
    			return ;
    			
    		}
    		System.out.println("当前运行的进程 :  " + Thread.currentThread().getName() + "  " + --TicketCenter.restCount);
    //		}
    }
    

      

    显式锁 : ReentrantLock  重入锁

    当接触临界区时 ReentrantLock 是在 Lock 接口实现的。临界资源由 lock() 和 unlock() 组成。lock() 就是让当前工作进程进入资源,然后使其他的试图进入临界资源的进程阻塞。

    ReentrantLock 能够让进程不止一次的进入资源。当这个进程第一次进入内存的时候,有一个计数器记为1,在解锁之前,一个进程又进入时,计数器递增1,每一次unlock() 时,计数器递减1。当计数器为0时,资源被解锁。

    Reentrant Locks 可重入锁还提供一个公平性参数,通过该参数,锁将遵守锁请求的顺序,即在线程解锁资源后,锁将转到等待时间最长的线程。此公平模式是通过将true传递给锁的构造函数来设置的。

    /*
     * 实例化一个锁对象
     */
    ReentrantLock lock = new ReentrantLock();
    
    Runnable r = () -> {
    	while(TicketCenter.restCount > 0 ) {
    		// 临界资源上锁
    		lock.lock();
    		
    		if (TicketCenter.restCount <= 0) {
    			return ;
    		}
    		System.out.println("当前运行的进程 :  " + Thread.currentThread().getName());
    		// 解锁
    		lock.unlock();
    	}
    };
    
    public void some_method() 
    { 
            reentrantlock.lock(); 
            try
            { 
                //Do some work 
            } 
            catch(Exception e) 
            { 
                e.printStackTrace(); 
            } 
            finally
            { 
                reentrantlock.unlock(); 
            } 
              
    }
    // volatile关键字 以及 CAS与原子变量使用的不多,这里就不再赘述了。
  • 相关阅读:
    docker pull配置代理方法
    docker配合ssh管道跨主机传输镜像
    Java面向对象详解
    云服务器的公网IP和内网IP的区别
    开启 kubectl 命令的自动补全功能
    Vue+Openlayers实现绘制线段并测量距离显示
    Vue+Openlayers+elradio实现切换地图显示
    koa使用swagger自动生成接口文档
    什么是低代码
    前后端统一接口的响应参数数据结构
  • 原文地址:https://www.cnblogs.com/qianyuesheng/p/11671507.html
Copyright © 2011-2022 走看看