目录
为什么Thread类的sleep()和yield ()方法是静态的?
什么是Java Timer 类?如何创建一个有特定时间间隔的任务?
Java 变长参数是什么?
1、Java 5 中开始提供了变长参数,允许在调用方法时传入不定长度的参数,本质上还是基于数组的实现。
2、定义方法时,最后一个形参类型后加上三点“…“,就表示该形参可以接受多个不定的参数值
public class ArrayTest {
/**
* 方法定义 可变参数
* @param infos
*/
public void show(String... infos) {
System.out.println(Arrays.toString(infos));
}
/**
* 方法定义 可变参数
* @param id
* @param infos
*/
public void show(String id, String... infos) {
System.out.println(id + ":" + Arrays.toString(infos));
}
}
注意事项
1)变长参数只能作为函数的最后一个参数,其前面可以有也可以没有任何其他参数
2、由于可变参数必须是最后一个参数,所以一个函数最多只能有一个可变参数
3、Java 的可变参数,会被编译器转型为一个数组,所以完全可以将变长参数看成是一个数组
4、调用一个被重载的方法时,如果此调用既能够和固定参数的重载方法匹配,也能够与可变长参数的重载方法匹配,则只匹配固定参数的方法
5、调用一个被重载的方法时,如果此调用既能够和两个及以上可变长参数的重载方法匹配,则编译出错
调用可变参数方法
调用可变参数方法,可以是传递零到任意个参数,编译器会将可变参数转化为一个数组,所以也可以直接传递一个数组。
/**
* 方法定义 可变参数
* @param id
* @param infos
*/
public void show(String id, String... infos) {
System.out.println(id + ":" + Arrays.toString(infos));
}
public static void main(String[] args) {
Test test = new Test();
test.show("1000");
test.show("1001","唐伯虎");
test.show("1002","唐伯虎","祝枝山");
test.show("1003",new String[]{"唐伯虎","祝枝山","文征明"});
//依次输出:
//1000:[]
//1001:[唐伯虎]
//1002:[唐伯虎, 祝枝山]
//1003:[唐伯虎, 祝枝山, 文征明]
}
使用场景
在不确定方法需要处理的对象的数量时可以使用可变长参数,会使得方法调用更简单,无需手动创建数组 new T[]{…}
什么是初始化数据块?
1、初始化数据块——当创建对象或加载类时运行的代码,有如下两种类型的初始化数据块:
静态初始化:加载类时运行的的代码,只在类加载时运行一次
实例初始化:创建新对象时运行的代码,每次创建都会运行
静态初始化
1、如下所示 static{ } 之间的代码被称为静态初始化数据块,只有在第一次加载类时运行。
2、只有静态变量才可以在静态初始化中进行访问并使用。
3、无论创建了多少个实例,静态初始化只在第一次加载时运行一次。
public class Test {
private static int count;
/**只在第一次加载本类时运行static中的代码
* 因为 static{}中的代码是在类加载时执行,所以里面的成员变量也必须是 static 修饰
* */
static {
count = 100;
System.out.println("init data:" + count);//init data:100(只会输出一次)
}
public static void main(String[] args) {
Test test_1 = new Test();
Test test_2 = new Test();
Test test_3 = new Test();
//虽然创建了3个对象,但是 static {}中的代码只会在类加载的时候执行一次
System.out.println(count);//100
}
}
实例初始化
1、如下所示成员变量的位置中的 {}中的代码就称为实例初始化代码
2、实例初始化代码每次在创建类实例的时候都会运行一次
public class Test {
private static int count = 100;
{
//花括号中的实例初始化代码,在每次创建本类实例的时候,都会被运行一次
System.out.println(count++);
}
public static void main(String[] args) {
Test test_1 = new Test();
Test test_2 = new Test();
Test test_3 = new Test();
//连续创建了3个对象,则上面花括号会执行3次。依次输出如下:
//100
//101
//102
}
}
Java中Semaphore是什么?
1、Java中 的 java.util.concurrent.Semaphore 是一种新的同步类,它是一个计数信号量,信号量维护了一个许可证集合。
2、Semaphore 只对可用许可证的号码进行计数,并采取相应的行动,信号量常常用于多线程的代码中,限制访问某些资源(物理或逻辑的)的线程数目,比如数据库连接池。
3、可以参考《 Semaphore 计数信号量限制资源访问的线程数目》
什么是阻塞式方法?
1、阻塞式方法是指程序会一直等待该方法完成,期间不做其他事情,TCP 编程的 ServerSocket 的 accept() 方法就是一直等待客户端连接。
2、这里的阻塞是指调用结果返回之前,当前线程会被挂起,直到得到结果之后才会返回。此外,还有异步和非阻塞式方法在任务完成前就返回。
为什么Thread类的sleep()和yield ()方法是静态的?
1、Thread类的sleep()和yield()方法将在当前正在执行的线程上运行,在其他处于等待状态的线程上调用这些方法是没有意义的。
2、它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。所以设计成静态的。
什么是Java Timer 类?如何创建一个有特定时间间隔的任务?
1、java.util.Timer 是一个工具类,可以用于安排一个线程在未来的某个特定时间执行,或者周期是任务。
2、java.util.TimerTask 是一个实现了Runnable接口的抽象类,需要去继承这个类来创建自己的定时任务并使用Timer去安排它执行。
设计秒杀系统要考虑哪些点?
1、数据预热 秒杀都是瞬时操作,不要等流量来了再加载数据。可以提前对数据进行预热,比如加载到缓存等。
2、缓存 包括CDN缓存和数据缓存。保证缓存系统的高可用,数据随后落地。
3、解决超卖 引入MQ,串行化操作库存,达到阈值后不再消费,并关闭购买功能。或者直接操作缓存。
4、流量削峰 通过引入MQ,将耗时业务进行削峰,平稳处理用户需求。
5、熔断限流 熔断,优先保证主要业务的进行。限流,识别异常流量,进行封锁;同时,允许部分请求失败。
6、弹性扩容 在判断系统负载达到极限时,可以通过增加服务器的途径抵抗峰值。需要打通运维环境,能够快速扩容。