第十一次作业
1. 本周学习总结
1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容。
2. 书面作业
本次PTA作业题集多线程
1. 源代码阅读:多线程程序BounceThread
1.1 BallRunnable类有什么用?为什么代码中需要调用Thread.sleep
进行休眠?
- 支持了多线程,而且实现了Running接口。
- 休眠可以让其他线程完成当前工作,可以减少CPU占用的时间,避免程序出现长时间CPU占用100%的情况。
1.2 Ball.java只做了两件事,这两件事分别是什么?BallComponent对象是干什么的?其内部的ArrayList有什么用?程序运行过程中,生成了几个BallComponent对象?该程序使用了多线程技术,每个小球是分别在不同的线程中进行绘制吗? - 这是Ball的类,定义move()方法改变小球的位置;定义getShape()方法建立一个平面图像并返回
- BallComponent对象是将每个ball显示在画面上。
- ArrayList用来存放添加的小球。
- 定义add()方法添加小球;定义paintComponent()方法将每个ball显示在画面上。
- 每个小球都是在自己的线程中进行绘制的。
2. 实验总结:题集(多线程)
2.1 题目:6-1(Thread)、6-3(Runnable-匿名内部类)。
回答:a)通过定义Runnable接口的实现类来实现多线程,比继承自Thread类实现多线程有何好处?
- 适合多个相同程序代码的线程去处理同一资源的情况;可以避免由于有些单继承特性带来的局限;会使程序更加健壮,这样的话代码可以被多个线程共享,此时的代码和数据是相互独立的。
b) 5-1,5-3实验总结。 - 5-1实验总结:本题 用setDaemon()方法将t1设置为后台线程,该线程在程序终止的时候都会终止,但如果要是非后台线程,只要运行程序就不会终止。所以我们这边当main()方法执行完成后,就没什么能够阻止程序终止了,这样的话,主线程退出时,在main方法中所启动的线程t1也会自动结束。
- 5-2实验总结:主线程调用t1线程的join()方法后,将会被挂起,直到目标线程t1结束才会恢复,t1线程结束过后,才会执行main()的最后一句。
2.2 使用Lambda表达式改写6-3
//lamda表达式改写
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与停止线程)。
回答:a)需要怎样才能正确地停止一个运行中的线程?
- 使用flag标识符,或者使用volatile标志位来停止线程。
b)6-2实验总结。 - 当MonitorTask运行的时候,主要的功能是在检查送来的单词,如果包含"alien",就输出相应信息。然后要重新将word置为null。否则while条件始终满足,程序将陷入死循环。然后通过Thread的静态方法yield()切换到主线程的使用,来获得下一个输入;这个函数的关键是在于flag标识符,以此来终止线程。
3. 互斥访问
3.1 修改TestUnSynchronizedThread.java源代码使其可以同步访问。(关键代码截图,需出现学号)
4. 互斥访问与同步访问
完成题集6-4(互斥访问)与6-5(同步访问)
4.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法可以使用synchronized实现互斥同步访问,使用代码说明(请出现相关代码及学号)?
//201621123066冯一
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void deposit(int money) {
lock.lock();
try {
balance += money;
condition.signalAll();
} finally {
lock.unlock();
}
}
public void withdraw(int money) throws InterruptedException{
lock.lock();
try {
while (balance < money) {
condition.await();
}
balance -= money;
} finally {
lock.unlock();
}
}
4.2 同步代码块与同步方法有何区别?
- 同步方法直接在方法名前加上synchronized修饰,实现加锁功能;而同步代码块则在方法内部使用synchronized代码块,实现加锁功能。
4.3 实现互斥访问的原理是什么?请使用对象锁概念并结合相应的代码块进行说明。当程序执行synchronized同步代码块或者同步方法时,线程的状态是怎么变化的? - 进程间相互排斥的使用临界资源的现象,就叫互斥;原理为在程序中,每个对象都有一把锁,只有获得了对象锁,才能执行相应的synchronized代码块或者方法。
- 对象锁(synchronized修饰方法或代码块):当一个对象中有synchronized method或synchronized block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放。
public synchronized void deposit(int money) {
money++;
}
- 线程的状态:当没有获得对象锁的时候就进入Look Pool状态,等待同步锁被释放。同步锁释放后,线程进入Runnable状态。
4.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作? - 等wait;通知notify;互斥synchronized
5. 线程间的合作:生产者消费者问题
5.1 运行MyProducerConsumerTest.java。正常运行结果应该是仓库还剩0个货物。多运行几次,观察结果,并回答:结果正常吗?哪里不正常?为什么?
- 结果不正常,如图,原因是同步问题,Producer和Consumer的存取速度不同导致的。
5.2 使用synchronized, wait, notify
解决该问题(关键代码截图,需出现学号)
//201621123066 冯一
public synchronized void add(String t){
while ( repo.size()>=capacity){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("仓库已满!无法添加货物");
}
repo.add(t);
notifyAll();
}
public synchronized void remove(){
while(repo.size()<=0){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("仓库无货!无法从仓库取货");
}
repo.remove();
notifyAll();
}
6. 面向对象设计作业-图书馆管理系统
6.1 系统的功能模块表格,表格中体现出每个模块的负责人。
功能 | 负责人 |
---|---|
图书的添加书籍,借阅书籍操作,还书操作 | 徐建民 |
Person类和Shuji类 | 冯一 |
主函数Main | 陈伟杰 |
6.2 运行视频 | |
6.3 讲解自己负责的模块,并粘贴自己负责模块的关键代码(出现学号及姓名)。
- 我写的是Person类和Shuji类里面主要是一些使用者的基本信息,并且在Person 类里用ArrayList存储借阅书籍的信息。
3.码云及PTA
题目集:多线程
3.1. 码云代码提交记录
在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
必须出现几个要素:提交日期-用户名(姓名与学号)-不提交说明
3.2 截图"多线程"PTA提交列表
需要有两张图(1. 排名图。2.PTA提交列表图)
3.3 统计本周完成的代码量
需要将每周的代码统计情况融合到一张表中。
周次 | 总代码量 | 新增代码量 | 总文件数 | 新增文件数 |
---|---|---|---|---|
1 | 0 | 0 | 0 | 0 |
2 | 492 | 492 | 10 | 10 |
3 | 435 | -57 | 6 | -4 |
4 | 0 | 0 | 0 | 0 |
5 | 312 | -123 | 8 | 2 |
6 | 525 | 213 | 7 | -1 |
7 | 236 | -289 | 3 | -4 |
8 | 305 | 69 | 3 | 0 |
9 | 183 | -122 | 5 | 2 |
10 | 312 | 129 | 3 | -2 |
11 | 173 | -139 | 5 | 2 |
12 | 176 | 3 | 7 | 2 |