文章目录
简介
- 本文是2021/04/11整理的笔记
- 赘述可能有点多,还请各位朋友耐心阅读
- 本人的内容和答案不一定是最好最正确的,欢迎各位朋友评论区指正改进
throw与throws的区别
- throws 写在方法签名后面 可以声明抛出多个异常类型,用逗号隔开
- throw 写在方法体内 一次只能抛出一个异常类型对象
throw可以写在方法的任何地方 try catch finally 都可以
当异常处理中存在return时,finally的执行特征
- finally语句块之前存在return语句的话,finally中的语句部分依然会执行。
- 异常处理机制(try-catch-finally)中如果出现了return语句或者异常
执行顺序:
(1)返回值
a.如果有返回值,存储在一个局部变量中
b.执行jsr指令跳转到finally语句
c.从finally语句向上返回,返回值从之前保存的局部变量中取。
(2)异常
a.将异常保存在一个局部变量中
b.执行jsr指令跳转到finally语句
c.从finally语句向上返回,重新抛出异常。 - 拓展:jsr命令(Java Specification Requests,Java规范提案)中有一个跳转程序Jump Subroutine,可以实现在return语句执行前,先执行finally块中的内容。
fina块前有System.exit(0)语句时,代码的执行过程
- System.exit(0)是System类中的exit方法,可以终止当前运行的虚拟机。
- 虚拟机被关闭了,finally语块无法被执行。
try catch finally 中存在return,代码的执行顺序(共有4种情况)
1.try中有return finally中没有return
public class Test1 {
public static void main(String[] args) {
int i = test1();
System.out.println(i);
}
//定义一个测试方法
private static int test1(){
int num = 10;
try {
System.out.println("try");
//先执行num+=80,存储在局部变量中,然后执行finally语句块中的内容,然后再执行return语句。
return num+=80;
}catch (Exception e){
System.out.println("Catch");
}finally {
if(num>20){
System.out.println("num>20:"+num);
}
System.out.println("finally");
}
return num;//不执行
}
}
程序运行结果
try
num>20:90
finally
90
2.try和finally中都有return
public class Test2 {
public static void main(String[] args) {
//输出test方法的返回值
System.out.println(test());
}
public static int test(){
int num = 10;
try{
System.out.println("try");
//由于finally块中存在return语句,所以不从try中跳出
//虽然这里执行了num+10,但是并没有赋值给num,而是存储在了某个局部变量中。
return num + 10;
}catch (Exception e){
System.out.println("catch");
}finally {
//num没有发生变化,还是10
System.out.println("finally"+num);
//跳出时返回num+10,结果为20
return num + 10;
}
}
}
程序运行结果
try
finally10
20
3.finally中赋值 (try中有return,finally中没有return)
public class Test3 {
public static void main(String[] args) {
//打印输出test方法的返回值
System.out.println(test());
}
public static int test(){
int num = 10;
try{
System.out.println("try");
//这里的return语句在执行前,会先把num的值存储起来, 然后去执行finally里的内容。
//所以即便在finally中对num进行赋值,也不会影响最终的return结果
return num;
}catch (Exception e){
System.out.println("catch");
}finally {
System.out.println("finally"+num);
num = 100;
}
return num;
}
}
程序运行结果
try
finally10
10
4.将数据用类包装起来
//定义一个Num类
class Num{
int number = 30;
}
public class Test4 {
public static Num method(){
//创建一个Num类对象
Num num = new Num();
try {
System.out.println("try");
return num;
}catch (Exception e){
System.out.println("catch");
}finally {
if(num.number>20) {
System.out.println("number>20:"+num.number);
}
System.out.println("finally");
//这里通过num对象直接修改了堆内存中成员变量的值。
num.number = 100;
}
return num;
}
public static void main(String[] args) {
//method方法的返回值是一个Num类对象,所以可以调用它的成员变量number
System.out.println(method().number);
}
}
程序运行结果
try
number>20:30
finally
100
断言(不常用)
assert 布尔表达式:错误信息
IDEA开启断言,Edit Configurations 在VM options 添加-ea
- 点击IDEA右上角小锤子右侧的选项,选择Edit Configurations
- 检查一下要添加断言功能的类的路径,然后在VM options中添加-ea
public class Test1 {
public static void main(String[] args) {
int i = 10;
assert i!=10 :"断言错误";
System.out.println("ok...");
}
}
程序运行结果
Exception in thread “main” java.lang.AssertionError: 断言错误
at demo04Assert.Test1.main(Test1.java:10)
并发与并行的基本概念
- 并发:指两个(或多个)程序在同一时间段内执行
- 并行:指两个(或多个)程序在同一时刻执行
程序 进程 线程的基本概念
- 程序:程序就是一段代码,程序是静态的。
- 进程:执行一个应用程序,就是一个进程。进程是动态的,有生命周期。
- 线程:线程是程序内部的执行路径,可以有多条。
- 三者的关系:程序运行至少有一个进程,一个进程可以有多条线程。
线程调度
分时调度
- 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度
- 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一
个(线程随机性),Java使用的为抢占式调度。
互斥锁
互斥锁用来保证在任何时刻,只有一个线程可以访问某块内存区域。
信号量
- 信号量是多线程环境下使用的一种设施,用来保证两个或多个代码段不被并发调用。
- 在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。
- 描述:
以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
进程和线程的区别
- 各进程是独立的。进程是程序运行的基本单位,有独立的内存空间和系统资源。
- 各线程可能会互相影响。线程是进程执行的最小单位,由处理器分配给线程空间和资源。
Thread类
创建线程的三种方式
1.继承Thread类
public class TestThread extends Thread{
}
public class Test{
public static void main(String[] args){
TestThread testThread = new TestThread();
}
}
2.实现Runnable接口(推荐使用)
(1)直接写一个Runnable接口的实现类,重写Runnable的run方法。该类对象作为Thread构造方法的参数
public class MyRunnable implements Runnable{
@Override
public void run() {
}
}
public class Test{
public static void main(String[] args){
MyRunnable myRunnable = new MyRunnable();
//Thread类有一个构造方法,参数为Runnable接口的实现类的对象
//传入myRunnable对象,向上转型
Thread thread = new Thread(myRunnable);
}
}
(2)匿名内部类
- 直接使用匿名内部类,不再单独写一个接口的实现类。
public class Test {
public static void main(String[] args) {
//匿名内部类的对象作为Thread构造方法的参数
Thread thread = new Thread(
new Runnable(){
@Override
public void run() {
System.out.println("Run方法重写");
}
}
);
}
}
(3)Lambda表达式
- 使用Lambda表达式对上一步进行简化
public class Test2 {
public static void main(String[] args) {
Thread thread = new Thread(
() -> {
System.out.println("Run方法重写");
}
);
}
}
3.实现Callable接口
JDK1.5后,出现了第三种创建线程的方式
import java.util.Random;
import java.util.concurrent.Callable;
//MyCallable实现类 实现Callable接口
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return new Random().nextInt(10);
}
}
//--------------------分割线--------------------------------
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//测试类
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建MyCallable对象
MyCallable myCallable = new MyCallable();
//创建一个任务futureTask对象
FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(myCallable);
//创建线程thread对象
Thread thread = new Thread(integerFutureTask);
//启动线程
thread.start();
//得到线程执行的返回值
System.out.println(integerFutureTask.get());
}
}
线程的启动
- 显示调用run方法不能达到并发的效果
- 线程调用start方法:JVM将会调用此线程的run方法
停止线程的方式
1.使用共享变量停止线程
//使用创建线程的第一种方式,继承Thread类
public class TestThread extends Thread{
//定义flag为true
private boolean flag = true;
//自定义停止线程的方法
public void stopThread(){
flag = false;
System.out.println("结束");
}
@Override
public void run() {
while(flag){
System.out.println("TestThread.run([])方法:"+Thread.currentThread().getName());
}
}
}
//------------------------分割线-----------------------------
//测试类
public class Test {
public static void main(String[] args) throws InterruptedException {
//创建线程对象
TestThread testThread = new TestThread();
//启动线程
testThread.start();
//线程睡一会儿
testThread.stopThread();
}
}