命令行传参, 可以用java Xxx 10 20 这样的方式传参,或者用IDEA工具,传参如下
参数过多的优化
大部分编码规范,对形参个数有要求,若参数过多,可以将参数抽取出来,放到一个类中,比如ParameterXxx,这里就可以将上述形参放进去,也可以用Hashmap实现
异常 能处理尽量处理,若仅仅是捕获而没有任何方案的话,尽量交给调用者去处理,即抛出异常
线程
概念
程序:静态代码,一组指令的集合,
进程:正在运行的程序,是CPU资源分配的单位,它是生命周期,从生到死,比如Servlet,Spring的bean,
线程:是进程的一个子集,一个进程至少有一个线程,提高程序的执行效率。
并发:同一时间段内发生
并行:同一时刻发生。
一个java应用程序 java.exe 至少有三个线程:main()主线程,gc()垃圾回收机制,异常处理线程,如果发生异常,会影响主线程。
如何创建线程
public class Thread implements Runnable
注意:启动线程调用的是start方法,JVM会帮我们调用run方法,
观察Thread类的源码,发现如上,即Thread源码就是Runnable
继承Thread vs Runnable
1可以避免java中的单继承的局限性
2继承:线程代码存放在Thread子类方法中
3实现 线程代码存在接口的子类run方法中
4实现解耦操作,代码可以被多个线程共享,代码和线程独立,耦合和解耦
5线程池只能放入实现Runnable或Callable类线程,不能直接放入继承Thread的类
Runnable vs Callable
共同点:都是函数式接口 而且都可以作为线程池参数
Runnable的run方法,没有返回值,没有异常
Callable的call方法,有返回值,有异常
方式1
继承Thread类
写一个继承Thread
重写run方法
创建线程 并启动start
方式2实现Runnable接口
创建一个类 实现Runnable
创建一个Runnable的子类对象,即多态的使用
创建Thread对象,用2作为实参传递 调用start方法
观察发现 Runnable 是一个函数式接口,就可以使用lambda表达式
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
使用方式
创建一个子类
使用匿名内部类
可以使用lambda创建
方案3实现callable接口
源码接口
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
方法4使用线程池
Thread常用方法
构造方法
不是很重要的方法
public long getID()获取线程编号
public final String getName() :获取线程名字
public final int getPriority() :获取当前线程的优先级 ----> 优先级范围为多少,默认多少
public State getState() :获取当前线程的状态 ----》状态有哪几种?
public final native boolean isAlive() :判断当前线程是否存活
重要方法
public static native void sleep(long millis):
单位是毫秒 可以让我们当前线程睡一会儿
这个方法在调用的时候可能会出现InterruptedException
静态方法
public final join()强行插队
public static native void yield()礼让 有可能成功,有可能不成功,而且这个方法是一个静态方法,注意跟上面join对比
线程分类
线程分为两类 用户线程 守护线程 (后台线程)
注意:在启动线程之前,调用t.setDaemon(true)将线程设置为守护线程
main线程有好几个守护线程 比GC回收的
线程优先级 了解
优先级只保证这个线程获取到CPU优先的概率,并不一定优先
跟优先级有关的方法setPriority(int newPriority) 和 public final int getPriority()
优先级如下
线程状态(java面试重点)
public State getState()
线程安全问题
多个线程在共享资源,(你的线程类中的成员变量),可能会引发的问题,比如卖票的错票,重票的问题,如何解决呢,为可能导致线程安全的代码加锁,可以通过synchronized去为方法或者代码块加锁,
1使用 synchronized 修饰方法的时候,粒度比较粗,即不管该方法,哪块代码可能有线程安全问题,我们不管,整体加锁,JDK6以前,这个锁比较重,我们称之为重量级锁,JDK6之后 做出了很大优化
2使用synchronized
为代码块加锁 可以使用对象锁,(这个锁对象可以是任意对象,一般可能直接使用this)类似自动化的东西,我们称之为隐式锁
3使用显示锁,ReentrantLock,该类是Lock接口的实现类,若自己去封装一般锁的话就可以模仿这个类去实现,这个锁也比较灵活,但是它需要自己去手动上锁,和解锁。。
线程状态转换图