1. 本周学习总结
1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容。
创建自己的异常
- 1.自定义异常要继承已有的异常,需要手动throw异常;根据继承的异常不同以及具体情况,选择try-catch或由系统抛出。
- 2.异常最好能够有详细的提示信息,方便用户明白错误发生的地方,尽量使用JDK已有的异常,重用,便于理解。
- 3.不要滥用异常,异常使程序性能降低,如果捕获异常后执行正常程序语句,那大可不用异常。
调试技术
- 1.使用输出,打印变量值
- 2.每个需要测试的类中,放一个main方法
- 3.Junit单元测试框架
- 4.日志
- 5.Throwable的printStackTrace方法,追踪输出至标准错误流
- 6.System.err用于出错信息的输出
- 7.将错误信息保存在文件中java Test 2 >errors.txt
- 8.java -verbose观察类的加载过程
- 9.jconsole图形工具
多线程
- 1.进程是指运行中的程序。每个进程都有自己独立的内存空间,可同时运行多个线程,完成不同的任务。查看任务管理器,出现javaw.exe进程文件
- 2.当生成一个Thread对象就产生一个线程。创建线程的方式:创建继承Thread的类,并覆盖run方法,并创建实例(不推荐,开销大);创建实现Runnable接口的类,实现run方法,将类作为实例化Thread的参数传入(常用)。注意:实现了Runnable的类为一项任务,可供多个线程同时进行。在主函数中调用线程的run方法,表示单纯调用该方法的内容
- 3.Thread的常用方法。run()-运行时所执行的代码,start()-启动线程,sleep()-休眠,不消耗CPU资源,join()-等待线程结束(在start后调用),yield()-暂停当前线程,让其他线程执行,放弃CPU
- 4.守护线程,为其他线程提供服务,当所有前台线程执行结束,守护线程自动结束,JVM执行完毕。setDaemon(boolean)(在创建前调用)isDaemon()-判断是否是守护线程
- 5.线程的生命周期:new-Runnable-Running-阻塞-Dead
- 6.线程的终止:使用stop()方法强行终止(不推荐,可能出现问题);采用boolean标志,使完成程序的流程再终止(推荐)
- 7.线程的调度-让出控制权:sleep()、yield()(使线程处于Runnable状态,可用Thread.sleep(1)代替)、join()(start后)
2. 书面作业
本次PTA作业题集异常
、多线程
1. finally
题目4-2
1.1 截图你的提交结果(出现学号)1.2 4-2中finally中捕获异常需要注意什么?
finally的作用是正确关闭资源,在关闭资源的过程中可能发生异常,需要进行捕获。虽然这里的异常是RuntimeException,但如果不手动try-catch,相当于让虚拟机帮我们抛出,与题目的要求不符。
2. 用异常改进ArrayIntegerStack
题目4-3
2.1 截图你的提交结果(出现学号)2.2 实验总结
FullStackException
该异常java中没有,需要自己定义,该异常继承Throwable
或Exception
时,需要在抛出该异常的方法外throws该异常;如果继承自RuntimeException
,则无需throws。EmptyStackException
该异常继承自RuntimeException
,抛出该异常的方法外无需throws,但是如果添加了throws,PTA上提示答案错误。
3. 自定义异常
题目5-4
4.1 截图你的提交结果(出现学号)4.2 自定义异常有哪几个关键点?
自定义异常必须继承异常,如果在抛出异常时有提示信息,则要在自定义异常类中编写构造函数,
super(s)
,使用父类的方法返回提示信息。当继承自RuntimeException
或其子类时,抛出异常的方法外可不声明异常。在main方法中需要使用try-catch捕获异常并处理。
4. 读取文件并组装对象
实验任务书中中的题目3:读取文件并组装对象
给出关键代码(需出现你的学号)public class ReadFileUsingScanner201521123037{ public static void main(String[] args) throws FileNotFoundException{ Scanner in = new Scanner(new File("身份证号.txt"));//为myfile.txt这个File创建一个扫描器in Listuser=new ArrayList (); int count=0; while(in.hasNextLine()){ String line = in.nextLine();//读出myfile.txt的下一行 count++; Scanner lineScanner = new Scanner(line);//为每一行建立一个扫描器 //System.out.println("lineScanner="+lineScanner); lineScanner.useDelimiter(" ");//使用空格作为分隔符 //System.out.println(line); try{ String a1 = lineScanner.next();//姓名 String a2 = lineScanner.next();//身份证号 String a3 = lineScanner.next();//性别 String a4 = lineScanner.next();//年龄 String a5 = lineScanner.next();//地址 while(lineScanner.hasNext()){//谨防地址只有一段 a5 += lineScanner.next(); } try{ if(a1==null) throw new NullPointerException("姓名为空"); else if(a1.length()>10) throw new NoSuchElementException("输入的姓名有误"); if(a2==null) throw new NullPointerException("身份证号为空"); else if(a2.length()!=18) throw new NoSuchElementException("输入的身份证号有误"); if(a3==null) throw new NullPointerException("性别为空"); else if(!a3.equals("男")&&!a3.equals("女")) throw new NoSuchElementException("输入的性别有误"); if(a4==null) throw new NullPointerException("年龄为空"); if(a5==null) throw new NullPointerException("地址为空"); user.add(new User(a1,a2,a3,Integer.parseInt(a4),a5)); System.out.println(a1+a2+a3+a4+a5); }catch(Exception e){ System.out.println("错误发生在第"+count+"行"); System.out.println(e); System.out.println("该行的内容为:"+a1+a2+a3+a4+a5); } }catch(NoSuchElementException e){ continue; } } user.sort(new Comparator (){ @Override public int compare(User o1, User o2) { return o1.getAge()-o2.getAge(); } }); System.out.println(user); in.close(); }}
- 运行结果的部分截图
5. 学会使用Eclipse进行调试
观看相关调试视频
5.1 简述使用Eclipse进行调试需要几步?设置断点->进入调试模式->根据具体情况点击调试快捷键->查看状态值->发现错误在哪->取消断点,关闭调试->更改源代码
5.2 调试时F5, F6, F7快捷键各有什么不同?什么情况该使用哪个快捷键?
F5-step into(单步调试进入函数内部);F6-step over(单步调试不进入函数内部);F7-step return(由函数内部返回到调用处)。当需要深入了解函数内变量的变化则按F5;查看下一步变量的变化并不需要深入了解函数内部怎么变化时按F6;当想跳出函数后观察变化则按F7。
5.3 除了Eclipse的调试器,你还使用什么方法调试程序?
还使用
Sysout.out.println();
语句进行调试,可以更加清楚变量的值以及运行的过程。
5.3 选做:实验任务书中的题目5:使用Eclipse进行调试中的选做
查看蓝山兰
i=5时数组值的排列
设置第9861次,断点才起作用
6. 题集多线程
6.1 程序填空3-1、3-2。(截图提交结果,出现你的学号)
6.2 函数4-1(Thread)、4-2(Runnable)(截图提交结果,出现你的学号)
6.3 函数4-3(Runnable与匿名内部类)(截图提交结果,出现你的学号),并使用Labmda表达式改写。
- Labmada表达式改写
new Thread( ()->{ System.out.println(mainThreadName); System.out.println(Thread.currentThread().getName()); System.out.println(Arrays.toString(Thread.class.getInterfaces()));//将原来的getClass()改为Thread.class,否则编译出错。 } ).start();
6.4 实验总结
3-1 这题使用了Thread的setDaemon(boolean)方法,这个方法的作用是标记线程为守护线程,注意要在启动线程前调用,虚拟机等到所有非守护线程结束后才执行结束。
3-2 这题调用了Thread的join()方法,作用是等待线程的结束,注意在启动线程后调用,调用这个方法,则主线程暂停执行,等待该线程执行完毕后继续执行。
4-1 在MyThread中写有参构造函数,在run方法中使用for循环遍历输出最后打印表示信息。currentThread()表示当前的线程;getName()表示线程的名称;isAlive()表示线程的存活状态。
4-2 这一题花了很长的时间,一直以为只要输入的字符串中有alien就跳出无限循环,也不能明白正常终止线程和没有终止线程的错误提示,后面在同学的帮助下才完成。注意在判断word中含有alien时候要增加一个条件word!=null,因为一开始,word的值为空,运行时提示NullPointerException异常。当word中有alien时,需要将word置null,否则会陷入无限循环中。
4-3 掌握匿名内部类的使用,在Thread中实现Runnable接口的run方法。
7. 源代码阅读:多线程程序BounceThread
7.1 哪个类是支持多线程的类,它实现了什么接口。这个类做了些什么?
BallRunnable
这个类,它实现了Runnable
接口。这个类移动了圆球的坐标,并休眠了5毫秒。
7.2 Ball.java这个程序只做了两件事,这两件事分别是什么?
获取小球的当前坐标以及大小,对当前的小球坐标设置移动的下一个坐标。
7.3 BallComponent也只做了两件事,这两件事分别是什么?
添加小球以及画出小球。
7.4 BounceThread中,什么时候启动了新线程?
点击Start按钮时,调用addBall()方法,触发新线程。
7.5 这个程序是如何实现?一个大致的执行流程是什么?
该程序采用图形界面,监听相应的按钮并进行操作,添加球的个数或退出程序,添加球的个数后开启线程,进行小球的移动。点击一次Start按钮则出现一个小球按照固定的线路进行跳动并最终在一个固定的位置停止,当点击Close按钮时则退出改程序。
8. 购物车系统中的多线程
8.1 购物车系统中可能存在哪些多线程问题?
多个用户多线程,对于商品的出售,商品的库存是一定的,会随着每个线程的选择发生变化;一个用户同一时间登入不同设备的多线程,如购物车、个人信息会随着每个线程的操作变化而变化。
9. 选做:单元测试JUint4
实验任务书中的题目6:单元测试使用JUnit4。
10. 选做:JavaFX入门
如果未完成作业1、2的请先完成。如果已完成的请完成第五部分:将数据用 XML 格式存储或第六部分:统计图(漂亮的图表)。注:内有代码,可在其上进行适当的改造。建议按照里面的教程,从头到尾自己搭建。
3. 码云上代码提交记录
题目集:异常、多线程(3-1, 3-2, 4-1, 4-2, 4-3)
3.1. 码云代码提交记录
在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
4. 选做:课外阅读
4.1 Java Concurrent Animated
4.2 线程的高级知识笔记