java程序员技术树(学不会就是老师不够牛皮)

说明:文章提到视频博客,基本都看过,略过业务代码、前端代码,有问题可以留言,会及时改正回复

java基础

毕向东天下第一:java基础

JDK下载,环境变量配置

多线程

  • 四种创建线程的方式
package com.learn.basic.thired.四种创建线程的方式;

import java.util.concurrent.*;

/**
* 1.继承Thread
* 2.实现接口Runnable
* 3.实现接口Callable 之后+FutureTask(可以拿到返回结果,可以处理异常)
* 4.线程池
*/
public class ThreadDemo {
  //创建线程池
  public static ExecutorService service = Executors.newFixedThreadPool(5);

  public static void main(String[] args) throws ExecutionException, InterruptedException {
      /**
       * 1.Thread
       */
      new Thread01().start();
      /**
       * 2.Runnable
       */
      new Thread(new Runnable01()).start();
      /**
       * 3.Callable
       * FutureTask继承关系可以看到,它就是一个Runnable
       */
      FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
      new Thread(integerFutureTask).start();
      //阻塞等待任务执行完,取任务返回结果
      Integer integer = integerFutureTask.get();
      System.out.println(integer);
      /**
       * 4.线程池本质都是[ExecutorService]
       * 可以执行Runnable,或Callable(当线程池只有一个线程时,可以看到每次用的线程都是同一个)
       */
      service.submit(new Runnable01());
      Future<Integer> submit = service.submit(new Callable01());
      System.out.println(submit.get());
  }

  public static class Thread01 extends Thread {
      @Override
      public void run() {
          System.out.println("线程" + Thread.currentThread().getName());
      }
  }

  public static class Runnable01 implements Runnable {
      @Override
      public void run() {
          System.out.println("线程" + Thread.currentThread().getName());
      }
  }

  /**
   * Callable允许异步任务有返回值
   */
  public static class Callable01 implements Callable<Integer> {
      @Override
      public Integer call() {
          System.out.println("线程" + Thread.currentThread().getName());
          int i = 10 / 2;
          return i;
      }
  }
}
package com.learn.basic.thired;

/**
 * @author 11695
 */
public class ThreadTest {
    /**
     * 多线程卖票的例子,多次运行发现结果有负数(线程安全问题)
     * 解决:在while循环里加上synchronized ()
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Ticket());
            thread.start();
        }
    }
    static class Ticket implements Runnable {
        private static int i =10;
        @Override
        public void run() {
            while (i>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i--);
            }

        }
    }
}
  • 线程池ThreadPoolExecutor

package com.learn.basic.thired.线程池;

import java.util.concurrent.*;

/**
 * ThreadPoolExecutor的七大参数
 * int corePoolSize,核心线程数【一直存在】
 * int maximumPoolSize,最大线程数
 * long keepAliveTime,存活时间(线程数 - 核心线程数 = 多余的线程 多余的线程空闲时间大于存活时间,将被释放)
 * TimeUnit unit,存活时间的单位
 * BlockingQueue<Runnable> workQueue,阻塞队列(任务数250>最大线程数50),将未能执行的200个任务放入队列(当线程空闲时就会取队列里的任务),new LinkedBlockingDeque<>(),默认是Integer的最大值。会导致内存不足,最好自己指定
 * ThreadFactory threadFactory,线程的创建工厂(如制定线程的名称)Executors.defaultThreadFactory()默认线程工厂
 * RejectedExecutionHandler handler,阻塞队列满了,按照制定的拒绝策略,拒绝执行任务
 * 拒绝策略:DiscardOldestPolicy丢弃老任务
 *          CallerRunsPolicy不丢弃,同步调用
 *          AbortPolicy直接丢弃新任务,并抛异常
 *          DiscardPolicy直接丢弃新任务,不抛异常
 *
 * <p>
 * 工作顺序:
 * 1.创建线程池,准备core数量的线程
 * 2.core满了,再进来的任务放入阻塞队列
 * 3.阻塞队列满了,开新线程,直到最大线程数
 * 4.最大线程数满了。按照制定的拒绝策略,拒绝执行任务(如果不想拒绝还要执行)
 * 5.任务执行完毕,空闲线程的空闲时间大于存活时间,就释放
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
        //原生方式new出来
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(1000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        /**
         * 使用Executors创建常见的4种线程池
         * newCachedThreadPool:核心线程数0,所有线程都可回收,无界队列
         * newFixedThreadPool:固定大小的线程池,核心线程数=最大线程数,所有线程都不可回收,无界队列
         * newScheduledThreadPool:定时任务的线程池,无界队列
         * newSingleThreadExecutor: 核心线程数=最大线程数=1,该线程池只有一个线程,无界队列,队列大小为Integer的最大值
         */
        Executors.newCachedThreadPool();
        Executors.newFixedThreadPool(10);
        Executors.newScheduledThreadPool(10);
        Executors.newSingleThreadExecutor();
    }
}
  • springboot项目中使用配置类配置线程池

package com.learn.mybatis.plus.config;

import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

@Configuration
public class ThreadConfig {
    /**
     * ThreadPoolExecutor创建线程池
     * @return
     */
    @Bean("threadPoolExecutor")
    public ThreadPoolExecutor threadPoolExecutor() {
        ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
        return taskExecutor;
    }

    /**
     * ThreadPoolTaskExecutor 创建线程池
     * 无界队列,最好指定下队列大小,任务太多会内存溢出,线程的最大值也没了意义
     * @return
     */
    @Bean("taskExecutor")
    public AsyncTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setThreadNamePrefix("线程名称");
        taskExecutor.initialize();
        return taskExecutor;
    }
}
  • 异步注解@Async的使用
    springBoot启动类上添加注解@EnableAsync开启异步调用
    在service的实现类里面创建方法,在其他类中调用(本类调用无效同@Transactional,原因spring的动态代理)

/**
* 使用上面创建的线程池 @Async("线程池的名称")
*/
 @Async("threadPoolExecutor")
 public void testAsync() {
      System.out.println(Thread.currentThread().getName());
}
  • ForkJoinPool的使用配合java8并行流parallelStream

package com.learn.basic.thired.forkjoin;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;

public class ForkJoinDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        ForkJoinPool forkJoinPool = new ForkJoinPool(50);
        ForkJoinTask<?> forkJoinTask = forkJoinPool.submit(() -> {
                    list.parallelStream().forEach(System.out::println);
                }

        );
        forkJoinTask.get();
    }
}

集合框架

Collection

List
ArrayList(多线程,数组,查询快,增删慢)

为什么叫可变长度数组:默认长度10,长度超过10时new新数组50%延长,新数组的size=15,将原来的数组装进新数组,再将新元素放入

LinkList(链表,查询慢,增删快)
Vector(单线程,数组,查询慢,增删慢,被淘汰)

默认长度10,长度超过10时new新数组100%延长,新数组的size=20

Set
HashSet

大神博客
底层数据结构:数组+链表,无序不重复
如何判断是否是同一元素:先判断hashcode,再判断eqals(都相同则认为是同一元素覆盖)
源码是用hashMap实现的
HashMap的键作为HashSet的值
HashMap的value,源码中PRESENT = new Object();就是new Object()作为值

TreeSet

底层数据结构是二叉树(是否是平衡二叉树,不知道),有序不重复
如何判断是否是同一元素:compareTo(Object obj)方法返回0,即相等,就认为是同一对象就不存入
可以将元素排序(根据Comparable排序)
如何才能具有比较性
1.让元素具有比较性:存入的对象元素须实现Comparable<T>接口覆盖compareTo(Object obj)方法;
2.让容器具有比较性:定义类如MyComparator,实现Comparator接口覆盖compare(Object o1,Object o2),使用构造函数TreeSet(new MyComparator())创建容器
3.当两种情况都存在时,以2为主

Map

HashTable

底层是hash表,不能存入null键null值,线程同步的

HashMap

底层是hash表,能存入null键null值,非线程同步的
put方法如果键相同,会覆盖原有的值,并返回原有值
大神博客:HashMap? ConcurrentHashMap? 相信看完这篇没人能难住你

TreeMap

底层是二叉树,非线程同步。可用于给map集合中的键进行排序(同TreeSet)

Collections

操作集合的工具类

Arrays

用于操作数组的工具类

泛型T,Object,?

可参考博客

package com.learn.basic.泛型;

import java.util.List;

/**
 * 影响范围 Object > T
 * <Object>可以传入任意类型
 * <T>只接收指定的类型。
 * 已知Number子类eg:Integer,Long,double等等
 * <? extends Number>,这就意味着只接收接收Number类以及类的继承类
 * <? super Integer>,这就意味着只接收接收Integer类以及Integer的父类Number,Object
 */
public class  GenericityDemo {
    /**
     * 可传入任意类型,返回Object类型
     */
    static Object demo001(Object obj){
        return obj;
    }
    static List<Object> demo0011(List<Object> objectList){
        return objectList;
    }
    /**
     * 可传入任意类型,返回类型同传入的类型
     */
    static <T> T demo002(T t){
        return t;
    }
    static <T> List<T> demo0022(List<T> list){
        return list;
    }
    /**
     * 可传入元素为Integer以及其父类,Number,Object的list
     */
    static  void demo003(List<? super Integer> list){
    }

    /**
     * 可传入元素为Number,以及其子类的list
     */
    static  void demo004(List<? extends Number> list){
    }

    /**
     * 同上,也就是说 ? extends 没什么用 ? super 才有意义
     */
    static  void demo005(List<Number> list){
    }
}

IO流

字符流

字节流

转换流

Java8

使用:
大神博客:新特性之流式数据处理
贴个自己的博客

springBoot

雷丰阳天下第一:
B站直达:springboot入门
B站直达:springboot高级
B站直达:谷粒商城–微服务分布式电商项目-分布式基础
官网:谷粒商城–微服务分布式电商项目-分布式基础

mybatisPlus

雷丰阳天下第一:mybatis-plus
mybatis-plus代码生成器

Linux

CentOS7
虚拟机搭建环境

centOS7下载安装(阿里云镜像下载,速度10M/s),(好用免费的工具VirtualBox,FinalShell比xshell更舒服)
安装Docker,以及使用Docker安装mysql,redis等

常用命令参考

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读