201521123036 《Java程序设计》第11周学习总结

本周学习总结

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



书面作业

本次PTA作业题集多线程

互斥访问与同步访问

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

1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步访问(请出现相关代码)?

也可以使用synchronized代码块,将属性balance上锁,生成对象锁,实现互斥同步访问。

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

answer:同步代码块只是对某些对象上锁,未获得对象锁就无法访问。而同步方法是对某个方法上锁,需要等待同步方法执行完毕返回结果。

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

answer:对同一资源进行存取时会出现互斥的现象。所以要对线程进行调度,对方法或对象上锁,调用时需要获得对象锁,如果没有对象锁就要等待同步锁被释放才能获取对象锁。当程序执行synchronized同步代码块或者同步方法时,线程先是获取CPU处于Running状态,获取对象的同步锁时,若该同步锁被别的线程占用就会进入Lock Pool中等同步锁释放再次进入Runnable。如果在进入块中执行了wait(),就会进入Wait Pool等待被notify/notifyAll唤醒,进入Lock Pool中。

1.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作?为什么同步访问一般都要放到synchronized方法或者代码块中?

answer:Java多线程中使用了wait () 和notify()/notifyAll()等关键字实现线程之间的通信。wait()可以使线程进入等待状态,再被其他线程notify()/notifyAll()唤醒,进而实现线程的协同工作。有了synchronized上锁后,其他线程才会等待同步锁释放并竞争获取锁,执行wait()会使线程放弃对象锁并堵塞,等到其他线程notify()唤醒时再重新进入等待同步锁释放并竞争同步锁的状态。

交替执行

4-6 实验总结(不管有没有做出来)

answer:Repo中存储不同的任务使用的是ArrayList,任务执行完直接用list.remove(0)移除此任务。两个线程交替执行时是对Worker1上锁,然后用wait()与notify中对线程进行调度。最开始是使用Synchronized对两个run方法上同步锁,再进行调度,出现了线程比较混乱的状况,每次的执行结果都不同。最后当list为空的时候,要终止线程。

互斥访问

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

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


运行结果:

参考资料:Java多线程之Executor、ExecutorService、Executors、Callable、Future与FutureTask


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

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

answer:结果不正常。会出现“仓库已满!无法添加货物。”,“仓库无货!无法从仓库取货”的错误提示。因为出项了互斥访问,无法同步对同一数据进行存取,线程混乱,结果就出现了这些问题。

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

4.3 选做:使用LockCondition对象解决该问题。


查询资料回答:什么是线程安全?(用自己的话与代码总结,写自己看的懂的作业)

answer:在多线程的情况下,可能会发生互斥,无法同步的问题。此时线程就会出现异常,或执行顺序混乱。比如消费者与生产者同时存取同一数据时就会产生互斥访问。线程安全是采用锁的形式对线程的执行顺序进行调度。可以使用synchronized, wait, notify或Lock或线程池来有序执行线程。比如可以在消费者与生产者互斥时,对add和remove方法上锁,使用wait, notify来调整获得对象锁的线程。

选做:实验总结

6.1 4-8CountDownLatch)实验总结

answer:此题需要使用的是执行器中的固定线程数线程池,即Executors.newFixedThreadPool(poolSize);poolSize为固定的线程数。CountDownLatch允许线程一直等待,直到其他线程的操作执行完后再执行。任务类要实现Runnable接口。

6.2 4-9(集合同步问题)实验总结

answer:使用Collections.synchronizedList解决集合的同步问题,确保线程安全

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

answer:4-10主要根据题目要求写,实现Callable接口的类里面要有call()方法,任务执行时会调用call()方法,并可将返回值提交到Future型的列表中,之后再依次读取。使用Callable可以得到返回值,便对计算结果进行验证。

###7.1 使用`BlockingQueu`e解决生产者消费者问题关键代码截图 ###7.2 说明为什么不需要显示的使用wait、notify就可以解决同步问题。这样解决相比较wait、notify有什么优点吗? ##选做:使用其他方法解决题目4的生产者消费者问题。 ###7.3 使用`Condition`解决生产者、消费者问题。

选做:编写一段代码,证明你会使用ForkJoinPool



码云上代码提交记录

题目集:多线程(4-4到4-10)

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

3.2 截图多线程PTA提交列表



选做:课外阅读

4.1 Questions and Exercises: Concurrency,学习总结。
4.2 Java多线程之Executor、ExecutorService、Executors、Callable、Future与FutureTask
4.3 Java 8 Concurrency Tutorial: Threads and Executors

posted @ 2017-05-06 18:02  扯扯扯  阅读(150)  评论(0编辑  收藏  举报