Java泛型、注解、线程池、同步操作

km # Java基础-泛型

泛型是解决什么问题的?

1.泛型是提供代码架构设计的抽象,设计类或者函数的时候,不指定具体类型,用泛型替代。
2.泛型解耦了代码和类型的耦合,提高代码复用性、稳定性、逻辑也更清晰。
泛型和Object的比较:
任何类的基类都是Object,任何子类对象传递给Object类型都是可以编译通过的。但是泛型如果赋值类型有误,编译阶段可以被检查出来。
泛型类:

public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;
    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }
    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}
Generic<String> fanxing = new Generic();
// 泛型函数
public static <K> void callFan(K k){
        System.out.println(k);
    }

Java基础-注解

注解可以实现面向切面编程,将一段可复用的通用逻辑注入到指定代码中。
注解声明的属性可以通过反射获取到。
实践:很多开源库用到。可以做一些代码检查。
例如:

@ReactProp(name = "setSupportMultipleWindows")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)`

注解定义:

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
}

@Documented作用是注解会不会出现在 javadoc 中
@Target 限制注解修饰的地方

public enum ElementType {
    TYPE,           /* 类、接口(包括注释类型)或枚举声明  */
    FIELD,           /* 字段声明(包括枚举常量)  */
    METHOD,           /* 方法声明  */
    ......
}

@Retention 限制注解修饰的策略,是在源码阶段,还是编一阶段,还是运行阶段

注解例子:

	// 定义注解
	@Documented
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation1 {
        String[] value() default "unknown";
        int data();
    }
    // 使用注解
    @MyAnnotation1(value = "test",data = 1)
    public static class FanXing<T>{}
     FanXing fanXing = new FanXing();
     // 反射获取注解定义的变量
     Class c = fanXing.getClass();
     if(c.isAnnotationPresent(MyAnnotation1.class)){
         MyAnnotation1 annotation =(MyAnnotation1) c.getAnnotation(MyAnnotation1.class);
         System.out.println(annotation.data()+" ___ "+annotation.value()[0]);
     }

Java基础-多线程

线程池

线程池是解决什么问题的?

线程创建销毁的成本比较大,频繁使用会耗费性能。
线程池提供线程复用机制,可以解决该问题。

默认几个构造线程池的API为什么被阿里规范禁止使用?

1.FixedThreadPool
创建一个固定线程数的线程池,核心线程数和最大线程数固定相等。
2.CachedThreadPool
corePoolSize为0,maximumPoolSize为无限大,意味着线程数量可以无限大。
3.ScheduledThreadPool
创建一个调度线程池,即按一定的周期执行任务,即定时任务
4.newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
不建议原因:
FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
CachedThreadPool 和ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

线程池应该怎么定义和使用。

核心的属性
加入自己设计线程池模型,应该是什么样的。
考虑几点:
1)池中最少有多少线程,没有task的时候有几个活的线程
2)池中最多有几个线程,满负荷运行是,还有task进来怎么办
3)可不可以根据task的数量动态修改线程数的上线?比如每阻塞10个task添加一个线程。
4)线程池为什么用阻塞队列

真实属性:
corePoolSize核心线程数。
maximumPoolSize最大线程数。
keepAliveTime 超过核心线程数的线程,空闲时间超过keepAliveTime时候,就会被杀死,如果配置了一个参数allowCoreThreadTimeout,核心线程也会因为空闲被杀死
TimeUnit keepAliveTime的单位
workQueue 阻塞线程
ThreadFactory 设定线程名、是否为daemon线程
RejectedExecutionHandler
当线程数量达到maxPoolSize时的处理策略

流程:
1.线程池初始化是空的
2.线程池达到核心线程数
3.超过核心线程数进入阻塞队列
4.阻塞队列满了继续创建线程
5.到达最大线程数
6.自定义处理查过最大线程数的情况
7.task减少,超过核心线程数的线程空闲时间到达定义值,开始销毁,最后衰减到核心线程数并保持。

上面问题思考
3)目的是根据实际task产生的频率和数量来控制线程个数,如果是后端服务,可以考虑动态配置
4)阻塞队列适用于生产消费场景,具有多线程锁的特性。

同步操作

Synchronized
Synchronized作用原理
作用是:
1.保证原子性,内部包裹代码要执行完才可以unlock
2.保证有序性,一个线程unlock才可以让另外一个线程访问
3.保证可见性,unlock之前要把变量同步到主缓存
作用范围:
类方法,普通方法,代码块。
原理:
在编译阶段生成monitorenter,monitorexit,相当于加锁。
ReetrantLock
ReetrantLock需要主动定义锁对象,并主动加锁。
ReetrantLock默认是非公平锁,就是不按照锁申请顺序来加锁。
Interrupt

BlockingQueue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值