201621123061《Java课程设计》第11次学习总结

1. 本周学习总结

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

  • 1.创建线程有两个方法,但我们一般只用中一个,即定义实现Runnable接口的类,实现它的run()方法,,然后将这个类的实例作为Thread构造方法的参数。
  • 2.Runnable是任务,只有Thread是线程。必须将实现Runnable的类的对象放入Thread中,才能在线程中运行。
  • 3.多线程的冲突可以用使用synchronized标记方法和标记代码块。
  • 4.volatile用来修饰变量,就会让变量之间具有可见性。

2. 书面作业

本次PTA作业题集多线程

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

1.1 BallRunnable类有什么用?为什么代码中需要调用Thread.sleep进行休眠?

BallRunnable类实现了Runnable接口,重写了Run方法,支持多线程指派任务,使用Thread.sleep进行休眠是为了让我们看清楚小球移动的轨迹,否则速度太快看不清楚。

1.2 Ball.java只做了两件事,这两件事分别是什么?BallComponent对象是干什么的?其内部的ArrayList有什么用?程序运行过程中,生成了几个BallComponent对象?该程序使用了多线程技术,每个小球是分别在不同的线程中进行绘制吗?

  • 定义了两个方法:分别是move()实现小球移动。getShape()获取坐标和大小。
  • 定义两个方法:分别是add()添加球球,和paintComponent()打印球球。ArrayList用来存放小球。
  • 运行过程,生成一个BallComponent对象。
  • 是。

1.3 选做:程序改写:程序运行时,每个小球都是从固定位置出发。如何改写该程序,使得当点击start时,每个小球可以从不同位置出发、以不同的步进移动?

每个小球可以从不同位置出发,也就是随机出发,那就使用Math.random().

   private double x = Math.random()*50;
   private double y = Math.random()*50;
   private double dx = Math.random()*5;
   private double dy = Math.random()*5;

1.4 选做:不同小球的移动轨迹一模一样。改造程序,使得每个小球运行轨迹不完全一样,比如有的可以走余弦轨迹、有的可以走方波轨迹、有的走布朗运动、有的走五角星,等等。

2. 实验总结:题集(多线程)

2.1 题目:Thread、PrintTask、Runnable与匿名内部类。

并回答:a)通过定义Runnable接口的实现类来实现多线程程序比通过继承自Thread类实现多线程程序有何好处?b) 6-1,6-3,6-11实验总结。

  • a).Java不能多继承,但是可以实现多个接口。
  • b).6-1 MyThread继承Thread,要重写run()。6-3.用Thread.currentThread().getName()可以获取当前的线程名字。6-11.这一题和6-1 Thread差不多,只不过一个是继承类,一个是实现接口。

2.2 使用Lambda表达式改写6-3

Thread t1 = new Thread(() -> {
            System.out.println(mainThreadName);
            System.out.println(Thread.currentThread().getName());
            System.out.println(Arrays.toString(Thread.class.getInterfaces()));
        });

2.3 题目:6-2(Runnable与停止线程)。回答:需要怎样才能正确地停止一个运行中的线程?

要对word判空,刚开始做的·时候没有判空会抛出空指针的异常。
在while循环时加个flag控制跳出循环,不要用stop不安全。

2.4 选做:6-8(CountDownLatch)实验总结

使用Executors类的newFixedThreadPool()方法创建一个线程池。

2.5 选做:6-9(集合同步问题)实验总结

用synchronizedList修饰list。

2.6 选做:较难:6-10(Callable),并回答为什么有Runnable了还需要Callable?实验总结。

3. 互斥访问

3.1 修改TestUnSynchronizedThread.java源代码使其可以同步访问。(关键代码截图,需出现学号)


3.2 选做:进一步使用执行器改进相应代码(关键代码截图,需出现学号)

4. 互斥访问与同步访问

完成题集6-4(互斥访问)与6-5(同步访问)

4.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法可以使用synchronized实现互斥同步访问,使用代码说明(请出现相关代码及学号)?

使用lock,unlock。

\\陈锦霞201621123061
public void deposit(int money) {
    lock.lock();
    try {
        this.balance += money;
        condition.signal();
    } finally {
        lock.unlock();
    }
}

public void withdraw(int money) {
    lock.lock();
    try {
        while (this.balance - money < 0) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        this.balance -= money;
        condition.signal();
    } finally {
        lock.unlock();
    }
}

4.2 同步代码块与同步方法有何区别?

使用synchronized关键字修饰的方法叫同步方法,此时内置锁会保护整个方法。锁的范围比较大。
使用synchronized关键字修饰的语句块叫同步代码块。被该关键字修饰的语句块会自动被加上内置锁,锁的范围比较小,性能较好。

4.3 实现互斥访问的原理是什么?请使用对象锁概念并结合相应的代码块进行说明。当程序执行synchronized同步代码块或者同步方法时,线程的状态是怎么变化的?

  • 通过获得唯一的锁来打开资源,其他线程就先等待,notify()之后进入Lock Pool,使用资源之后,就把锁还回去。

    th1获得id锁,读取值,th2等待,th1的id+1,将值传给id,锁被释放。th2获得锁,重复th1的步骤。
    线程变化:多个线程进行争夺对象锁,一个线程获得对象锁,其余等待该线程结束。

4.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作?

wait()和notify()。

5. 线程间的合作:生产者消费者问题

5.1 运行MyProducerConsumerTest.java。正常运行结果应该是仓库还剩0个货物。多运行几次,观察结果,并回答:结果正常吗?哪里不正常?为什么?

  • 不正常。每次结果都是不确定的。Comsumor和Producer的速度不一样,同时进行存取操作。冲突了。

5.2 使用synchronized, wait, notify解决该问题(关键代码截图,需出现学号)

//陈锦霞201621123061
class Repository {// 存放字符串的仓库
	private int capacity = 10;//仓库容量默认为10
	private List<String> repo = new ArrayList<String>();// repo(仓库),最多只能放10个

	public synchronized void add(String t) {
		while(repo.size() >= capacity) {
			System.out.println("仓库已满!无法添加货物。");
		 
		try{
			wait();
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
		repo.add(t);	
		System.out.println("已添加!");
		notify();
	}
	public synchronized void remove() {
		while(repo.size() <= 0) {
			System.out.println("仓库无货!无法从仓库取货");
			
		  try{
			wait();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
		repo.remove(0);	
		System.out.println("已取走!");
		notify();
}

5.3 选做:使用Lock与Condition对象解决该问题。

//陈锦霞201621123061
class Repository {// 存放字符串的仓库
	private int capacity = 10;//仓库容量默认为10
	private List<String> repo = new ArrayList<String>();// repo(仓库),最多只能放10个

	public synchronized void add(String t) {
		lock.lock();
		while(repo.size() >= capacity) {
			System.out.println("仓库已满!无法添加货物。");		 
		try{
			condition.await();
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
		repo.add(t);	
		System.out.println("已添加!");
		condition.signal();
		lock.unlock();
	}
	public synchronized void remove() {
		lock.lock();
		while(repo.size() <= 0) {
			System.out.println("仓库无货!无法从仓库取货");
			
		  try{
			  condition.await();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
		repo.remove(0);	
		System.out.println("已取走!");
		condition.signal();
		lock.unlock();
}

6. 面向对象设计作业-图书馆管理系统

6.1 系统的功能模块表格,表格中体现出每个模块的负责人。

我自己

6.2 运行视频

没有做出来,主要是时间太短,自己基础也并不好,模仿资料写的。

6.3 讲解自己负责的模块,并粘贴自己负责模块的关键代码(出现学号及姓名)。

只有一小部分代码

 import java.awt.*;
 import java.awt.event.*;
 import java.sql.*;
 import javax.swing.*;
 
 public class Login extends JFrame{
 	//声明标签、按钮、文本框和密码框
 	private JLabel JLb1;
 	private JLabel JLb2; 
 	private JButton Ok_btn;
 	private JButton Cancel_btn;
 	private JTextField jtflduser;
	private JPasswordField jtpwdfld;
 	//声明窗口
 	private JFrame frame;
 	//构造方法
 	public Login(){
 		frame=new JFrame("登录");
 		Container content=frame.getContentPane();
 		//采用GridLayout布局管理器
 		content.setLayout(new GridLayout(3,2,20,20));		
 		JLb1=new JLabel("用户名");
 		JLb2=new JLabel("密   码");
 		//将标签置于居中位置
 		JLb1.setHorizontalAlignment(SwingConstants.CENTER);		
 		JLb2.setHorizontalAlignment(SwingConstants.CENTER);
 		jtflduser=new JTextField();
 		jtpwdfld=new JPasswordField();
 		Ok_btn=new JButton("确定");
 		Cancel_btn=new JButton("取消");
 		//为按钮增加事件监听者
 		Ok_btn.addActionListener(new ActionHandler());
 		Cancel_btn.addActionListener(new ActionHandler());
 		//添加标签、文本框和密码框到窗口
 		content.add(JLb1);
 		content.add(jtflduser);
 		content.add(JLb2);
 		content.add(jtpwdfld);
 		content.add(Ok_btn);
 		content.add(Cancel_btn);
 		frame.pack();
 		//设定登录窗口启动时出现在屏幕中央位置
 		frame.setLocationRelativeTo(null);
 		frame.setSize(300,200);
 		frame.setVisible(true);
 	}//Login() method

 	/**
	 *实现ActionListener监听,激活组件响应
 	 */
 	 class ActionHandler implements ActionListener{
 	 	public void actionPerformed(ActionEvent e){
 	 		String str1,str2,sqlStr;
 	 		Object obj=e.getSource();
 	 		//获得文本框和密码框的数据
 	 		str1=jtflduser.getText().trim();
 	 		str2=new String(jtpwdfld.getPassword()).trim();
 	 		try{
 	 			//点击确定按钮
 	 			if(obj.equals(Ok_btn)){
 	 				if(str1.equals("")){
 	 					JOptionPane.showMessageDialog(frame,"用户名不能为空!");
 	 					return;
 	 				}
 	 				
 	 				if(result.next()){
 	 					//弹出对话框提示登录成功
 	 					JOptionPane.showMessageDialog(frame,"登录成功!");
 	 					//打开图书管理主页面
 	 					bookmain bookmain1=new bookmain();
 	 					bookmain1.go();
 	 					//关闭登录窗口
 	 					frame.dispose();
 	 					
	 				}else{ 	 					JOptionPane.showMessageDialog(frame,"用户名或密码错误");
 	 				}
 	 				
 	 			}else if(obj.equals(Cancel_btn)){
 	 				//点击取消按钮
 	 				System.exit(0);
 	 			}
 	 		}catch(ClassNotFoundException ce){
 	 			//捕获异常
 				System.out.println("SQLException:"+ce.getMessage());	
 			}
 	 		catch(SQLException ex){
 	 			//捕获异常
 	 			System.out.println(ex);
 	 		}
 	 		catch (Exception s) {
 	 			//捕获异常
 	 			s.printStackTrace();
 	 		}
 	 	}
 	 }
 	public static void main(String args[]){
 		 	 	Login login=new Login();
 		 	 }//main			
 		 }//class ActionHandler

这是用户界面
3.码云及PTA

题目集:多线程

3.1. 码云代码提交记录

在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
必须出现几个要素:提交日期-用户名(姓名与学号)-不提交说明

3.2 截图"多线程"PTA提交列表

需要有两张图(1. 排名图。2.PTA提交列表图)

3.3 统计本周完成的代码量

需要将每周的代码统计情况融合到一张表中。

周次 行数 新增行数 文件数 新增文件数
1 91 91 5 5
2 504 413 18 13
3 1092 588 28 10
5 1158 129 34 6
6 1539 381 40 6
7 2023 484 49 9
8 2477 454 57 8
9 2709 232 63 6
10 3156 447 70 7
11 3531 375 79 9
12 4083 552 91 12

posted on 2017-12-03 21:36  球球滚吧hhh  阅读(710)  评论(1)    收藏  举报

导航