201521123004 《Java程序设计》第10周学习总结

1. 本周学习总结

1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容。

答:
异常的概念上周的思维导图大致体现,这周就归纳一下错误调试

由于多线程的内容比较散,我就直接用文字总结

  • 进程与线程

    • 进程是指运行中的应用程序,每一个进程都有自己独立的内存空间
    • 线程是指进程中的一个执行流程
    • 线程不是程序,必须在程序对应的进程中运行
    • 一个进程可以由多个线程组成(在一个进程中可以同时运行多个不同的线程,分别执行不同的任务)
    • 并发运行是指进程内的多个线程同时运行(例如:QQ可以同时接收消息、发送消息、传送文件、界面绘制等)
    • 创建线程:生成一个Thread类的对象之后,产生一个线程
      • ×方法一:定义一个Thread类的子类,覆盖Thread类的run()方法,然后创建该子类的实例
      • ★方法二:定义一个实现Runnable接口的类,实现它的run()方法,然后将这个类的实例作为Thread的构造方法的参数,创建Thread类的实例
      • t1.start();//启动了线程
      • t1.run();//run方法并没有启动线程,只是在主线程中调用了 t1.run(); 方法
  • Runnable与任务

    • Runnable本身不是线程,只有Thread才是线程。必须将实现Runnable的类的对象放入Thread中,才能在线程中运行
Runnable task1 = new MyRunnable();
Thread t1 = new Thread(task1);//创建了一个任务对象task1,然后创建了线程t1,t1的任务就是以线程的方式运行task1
t1.start();
- ` new Thread(new MyRunnable()).start();`
    - 生成了一个任务对象(MyRunnable)
    - 生成了一个线程对象,并为该线程指派任务
    - 启动线程
- 使用Runnable可以将线程和任务这两个不同的概念相分离
  • 守护线程(Daemon Thread)
    • 如果所有前台线程死亡,守护线程自动结束(例如:word一旦关闭,word的提示,语法检查线程自动关闭)
    • 方法:setDaemon(true or false);
      Thread类还提供一个isDaemon方法,判断是否为守护线程
    • setDaemon(true):使线程成为守护线程(必须在start之前调用)
      setDaemon(false):使线程成为一般线程(必须在start之前调用)
  • 终止线程
    • ×可以通过在其他线程中调用stop()方法来终止线程,也可以由线程自己调用stop()方法,自我终止
    • ★如果希望线程正常终止,可采用boolean标志来使线程中的run()方法退出
  • 线程调度-让出控制权
    • 线程暂停:Thread.sleep()方法
    • 线程让步:Thead.yield()方法
    • 等待其他线程结束:Thead.join()方法
  • 多线程示意图

  • 多线程的状态转换过程

2. 书面作业:本次PTA作业题集异常、多线程

finally:题目4-2

1.1 截图你的提交结果(出现学号)

答:截图如下:

1.2 4-2中finally中捕获异常需要注意什么?

答:不管tyr-catch中是否捕获到resource.open(sc.nextLine());的异常,finally中的代码段是一定会被执行的,根据题目要求大致意思就是不管资源打开是否成功都要对resource.close();进行try-catch,所以要把对资源关闭的try-catch代码段放在finally的代码段内,如下代码所示:

finally{
    try{
    resource.close();
    System.out.println("resource release success");
    }catch(RuntimeException e){
    System.out.println(e);
}

拓展:分情况说说try-catch-finally的执行过程:

  • 在java 的异常处理中,在抛出异常的情况下,程序执行完 try-catch里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块
    • 如果没有 finally 代码块,整个方法在执行完 try-catch 代码块后返回相应的值来结束整个方法
    • 如果有 finally 代码块,此时程序执行到 try-catch 代码块里的 return 语句之时并不会立即执行 return,而是先去执行 finally 代码块里的代码
    • 若 finally 代码块里没有 return 或没有能够终止程序的代码,程序将在执行完 finally 代码块代码之后再返回 try-catch 代码块执行 return 语句来结束整个方法
    • 若 finally 代码块里有 return 或含有能够终止程序的代码,方法将在执行完 finally 之后被结束,不再跳回 try 代码块执行 return

用异常改进ArrayIntegerStack:题目4-3

2.1 截图你的提交结果(出现学号)

答:截图如下:

2.2 实验总结

答:4-3主要是对栈满栈空的异常处理,直接用if语句判断栈满或栈空(栈满:top>=capacity;栈空:top=0;),然后根据题目要求throw出FullStackException或EmptyStackException,此外,需要注意的是裁判测试代码中是没有对capacity和arrStack进行初始化定义的,需要我们自己写,但是pta的提交答案是不需要包括进去的,否则会编译错误的;

//初始化
public ArrayIntegerStack(int size){
    this.capacity=size;
    this.arrStack=new Integer[size];
}

主要代码如下:

自定义异常:题目5-4

4.1 截图你的提交结果(出现学号)

答:截图如下:

4.2 自定义异常有哪几个关键点?

答:
1.定义IllegalScoreException异常类属于checked exception(即希望该异常一定要被捕获处理)->继承自Exception

class IllegalScoreException extends Exception {
	public IllegalScoreException(String message){
		super(message);
	}
}

2.定义IllegalNameException异常类属于unchecked exception->继承自RuntimeException

class IllegalNameException extends RuntimeException {
	public IllegalNameException(String a) {
		super(a);
	}
}

3.自定义的异常在抛出时要明确告诉用户异常的原因:要求异常名要有意义,最好还要输出产生异常的信息,例如:

//由IllegalScoreException及括号内的信息明显看出其表示异常产生的原因:成绩是不符合要求的
if(score<0||score>100)
    throw new IllegalScoreException("score out of range, score="+score);

PS:关于5-4还有很重要的一点就是输出格式,空格什么的都要注意,我就是因为多了一个空格导致答案部分正确了好几次。

读取文件并组装对象(实验任务书中中的题目3:读取文件并组装对象)

给出关键代码(需出现你的学号)

答:对Scanner in = new Scanner(new File("身份证号.txt"));进行FileNotFoundException异常捕获,如果try-catch只包含该代码段,后面的所有信息录入都会出现问题,所以try-catch必须包含整段代码;对于信息不全的问题,在信息录入的时候对其进行判断,如果不符合要求就抛出异常

public class readFile004 {
	public static void main(String[] args) throws Exception {
		try {
			Scanner in = new Scanner(new File("身份证号.txt"));// 为myfile.txt这个File创建一个扫描器in
			ArrayList<User> arr=new ArrayList<User>();
			
			while (in.hasNextLine()) {
				String line = in.nextLine();// 读出myfile.txt的下一行
				Scanner lineScanner = new Scanner(line);// 为每一行建立一个扫描器
				// System.out.println("lineScanner="+lineScanner);
				lineScanner.useDelimiter(" ");// 使用空格作为分隔符
				// System.out.println(line);
				try{
				String a1 = lineScanner.next();// 姓名
				if (a1.isEmpty())
					throw new Exception("Name is null");
				String a2 = lineScanner.next();// 身份证号
				if (a2.isEmpty())
					throw new Exception("ID is null");
				String a3 = lineScanner.next();// 性别
				if (a3.isEmpty())
					throw new Exception("Gender is null");
				String a4 = lineScanner.next();// 年龄
				if (a4.isEmpty())
					throw new Exception("Age is null");
				String a5 = lineScanner.next();// 地址
				if (a5.isEmpty())
					throw new Exception("Address is null");
				while (lineScanner.hasNext()) {// 谨防地址只有一段
					a5 += lineScanner.next();
					System.out.println(a1 + a2 + a3 + a4 + a5);
					arr.add(new User(a1,a2,a3,a4,a5));
				}}catch(Exception e){
					System.out.println(e);
					continue;
				}
				
			}
			in.close();
		} catch (FileNotFoundException e) {
			System.out.println(e);
		}
	}
}

//排序
Collections.sort(arr, new Comparator<User>() {

	@Override
	public int compare(User o1, User o2) {
		// TODO Auto-generated method stub
		if(o1.getAge().compareTo(o2.getAge())>0)
		return -1;
		return o1.getAge().compareTo(o2.getAge());
		}
				    
});

学会使用Eclipse进行调试:观看相关调试视频

5.1 简述使用Eclipse进行调试需要几步?

答:
1.在正确的地方设置断点
2.启动调试模式
3.Eclipse有一个专门的debug perspective(长得像只萤火虫),专门用于调试
4.查看状态值

5.2 调试时F5, F6, F7快键键各有什么不同?什么情况该使用哪个快捷键?

答:
F5:step into
F6:step over,跳过
F7:step return,跳出
F8:resume,恢复运行直到碰到下一个断点

5.3 除了Eclipse的调试器,你还使用什么方法调试程序?

答:使用System.out.println("x="+x);打印出任意变量的值,如果碰上某个变量打印出现异常就能找到出错点

5.3 选做:实验任务书中的题目5:使用Eclipse进行调试中的选做

答:目前停留在调试阶段
登录调试没什么大问题

输入留言出错

题集多线程

6.1 程序填空3-1、3-2。(截图提交结果,出现你的学号)

答:截图如下:

6.2 函数4-1(Thread)、4-2(Runnable)(截图提交结果,出现你的学号)

答:截图如下:
函数4-1(Thread)

4-2(Runnable)

6.3 函数4-3(Runnable与匿名内部类)(截图提交结果,出现你的学号),并使用Labmda表达式改写。

答:截图如下:

lambda表达式改写如下:

     Runnable r=()->{
		System.out.println(mainThreadName);
        System.out.println(Thread.currentThread().getName());
        //System.out.println(Arrays.toString(getClass().getInterfaces()));//getClass()会报错
        System.out.println(Arrays.toString(Thread.class.getInterfaces()));//修改过后
       };
        Thread t1 =new Thread(r);

getClass()会报错

改写成功

6.4 实验总结

答:

  • 3-1考察守护线程setDaemon(true)的用法,主线程退出时,在main方法中所启动的线程也要自动结束即将线程t1设为守护线程,必须在start之前调用
  • 3-2考察join()方法,等其他线程执行完再执行本线程;线程打印完后,才执行主线程main方法的最后一句即采用t1.join();先执行t1,等t1结束后再执行main的最后一句。
  • 4-1考察Thread类的创建,因为继承自Thread,所以run方法编写时要super.run();根据裁判测试程序可以知道MyThread是带参的,所以在MyThread类中要写出如下代码:
        private int n;
	public MyThread(int n) {
		// TODO Auto-generated constructor stub
		this.n=n;
	}
  • 4-2题目要求每个传入的word只能检查一遍,所以就将检查过的word置为空,并在判断word与alien的时候多加一个判空的条件;在stopMe方法中使用Thread.yield();来阻止线程运行
  • 4-3要给t1编写一个匿名内部类使它能够完成三个输出任务,将三个输出写进新建的Runnable里,充当t1的匿名内部类即可

源代码阅读:多线程程序BounceThread

7.1 哪个类是支持多线程的类,它实现了什么接口。这个类做了些什么?

答:根据class BallRunnable implements Runnable,BallRunnable实现Runnable接口,是支持多线程的类;
让小球沿着运动轨迹走,走过的就sleep停止,继续走下一步,有点类似电影画面一幕一幕地跳过去,播放过的就sleep,继续播放下一个画面

    for (int i = 1; i <= STEPS; i++)
         {
            ball.move(component.getBounds());
            component.repaint();
            Thread.sleep(DELAY);
         }

7.2 Ball.java这个程序只做了两件事,这两件事分别是什么?

答:
1.球移动到下一个位置,如果它击中一个边缘就扭转方向,即使一个球在一个矩形的边缘移动和反弹
Moves the ball to the next position, reversing direction if it hits one of the edges.
2.在当前位置得到球的形状
Gets the shape of the ball at its current position.

7.3 BallComponent也只做了两件事,这两件事分别是什么?

答:
1.画出球的分量
The component that draws the balls.
2.在面板上添加一个球
Add a ball to the panel.

7.4 BounceThread中,什么时候启动了新线程?

答:在加入一个小球之后启动新线程

   public void addBall()
   {
      Ball b = new Ball();
      comp.add(b);
      Runnable r = new BallRunnable(b, comp);
      Thread t = new Thread(r);
      t.start();
   }

7.5 这个程序是如何实现?一个大致的执行流程是什么?

答:首先创建一个JavaFrame,编写一个Ball类规定小球的位置以及运动轨迹(沿矩形框运动),编写一个BallComponent画球以及添加球;当点击添加按钮后,一个小球进入界面,开始沿固定的轨迹运动,到达指定位置后停止运动,点击一次添加一个小球,做上述运动;点击关闭后,窗体关闭。

购物车系统中的多线程

8.1 购物车系统中可能存在哪些多线程问题?

答:例如淘宝上的一元抢购应该算是多线程吧,一样商品同时被多个用户抢购

3. 码云上代码提交记录

题目集:异常、多线程(3-1, 3-2, 4-1, 4-2, 4-3)

3.1. 码云代码提交记录:在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图

答:码云截图如下

4. 选做

选做:单元测试JUint4

实验任务书中的题目6:单元测试使用JUnit4。

选做:JavaFX入门

如果未完成作业1、2的请先完成。如果已完成的请完成第五部分:将数据用 XML 格式存储或第六部分:统计图(漂亮的图表)。注:内有代码,可在其上进行适当的改造。建议按照里面的教程,从头到尾自己搭建。

选做:课外阅读

4.1 Java Concurrent Animated

4.2 线程的高级知识笔记

原文地址:https://www.cnblogs.com/dabaolyr/p/6777747.html