1. 本章学习总结


2. 书面作业

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

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

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
synchronized void deposit(int money){
lock.lock();
try{
balance+=money;
condition.signal();
}finally {
lock.unlock();
}
}
synchronized void withdraw(int money){
lock.lock();
try{
while(balance<money){
try{
condition.await();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
balance-=money;
}finally {
lock.unlock();
}
}

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

  • 同步方法是直接在方法上加synchronized实现加锁,而同步代码块则是在方法内部通过synchronized(this){}实现加锁。因为同步方法锁的范围比较大,一般同步范围越大性能越差,如果只是让某些个线程不能同时访问方法内部的部分代码的话,应该采取同步代码,这样访问对象的时间性能就会比较好。
  • 举个例子
public synchronized void test1() {
System.out.println("hello");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void test2() {
synchronized(this) {
System.out.println("hello world");
}
} //hello world隔了五秒才运行,从这段代码可以看出如果将synchronized放在方法上,同步锁的范围是整个方法,所以test2想要获得对象锁必须等test1的方法全部执行完,也就是需要在休眠五秒后才能得到锁。

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

  • 每个对象都有一把锁,只有获得this对象上的内部锁,才可以访问该段资源,没有获得对象锁的线程在Lock Pool中,等待获得对象锁的线程运行完解锁,然后通过竞争获得对象锁再运行。也就是一段时间内只允许一个线程访问这段共享资源。

    class Counter {
    private static int id = 0;
    //当有线程1先对其调用addId方法,另一线程2调用subtractId方法,
    public static synchronized void addId() {
    id++; //线程1获得对象锁(线程2锁池中等待获得锁)对其id++,执行完后,释放this上的对象锁,
    } public static synchronized void subtractId() {
    id--; //另一线程2获得对象锁,对其id--,然后释放对象锁。
    } public static int getId() {
    return id;
    }
    }
  • 多个线程start(),竞争对象锁,某一线程竞争获得对象锁,其余线程在等待池中等待线程释放对象锁,当线程释放对象锁其余线程又开始竞争对象锁,直到程序结束。

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

  • 使用wait ()、notify()、notifyAll()实现线程之间的通信
  • 因为将共享资源放在synchronized方法或者代码块中就可以保证获得对象锁的线程可以在对共享资源进行操作的时候不被打扰,其他线程只能在其之后才能访问,避免了多个线程访问同一资源引起的冲突。

 
Q2.交替执行
 2.1 实验总结

public synchronized void jiaoti1(){
while(getSize()>0){
if(flag){
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
}
else {
System.out.println(Thread.currentThread().getName()+" finish "+str[i]);
i++;
flag=true;
notify();
}
}
}
...
  • 因为两线程交替执行所以需要wait()、notify()的协作。设置flag初始值为flase,执行了Woker1,置flag为true,唤醒Woker2。当Woker2执行完,再置flag为flase,唤醒Woker1,直到任务数为空。

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

//201521044091
public static synchronized void addId() {
id++;
}
public static synchronized void subtractId() {
id--;
}

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

                int n=3;
List<Callable<Object>> listtask=new ArrayList<>(); //创建Callable<Object>类型的listtask
ExecutorService exec=Executors.newCachedThreadPool();
for (int i = 0; i < n; i++) {
listtask.add(Executors.callable(new Adder())); //将返回的Callable对象加入listtask
}
for (int i = 0; i < n; i++) {
listtask.add(Executors.callable(new Subtracter()));
}
exec.invokeAll(task); // 使用ExecutorService接口的invokeAll(listTask)
System.out.println(Counter.getId());
System.out.println("main end");

Q4.线程间的合作:生产者消费者问题
 4.1 运行MyProducerConsumerTest.java。正常运行结果应该是仓库还剩0个货物。多运行几次,观察结果,并回答:结果正常吗?哪里不正常?为什么?

  • 不正常,有时会出现剩余货物还有10个,问题出现在public synchronized void add(String t)public synchronized void remove()。虽然这两个方法实现了synchronized,但是仓库只有一个当往仓库存入一个数据,而生产者和消费者的存取速度不一样,则有可能出现生产者比消费者快,消费者来不及取数据,或者反之,消费者取不到数据。

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

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

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

private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public synchronized void add(String t) {
lock.lock();
try{
while(repo.size()>=capacity){
try{
condition.await();
System.out.println("仓库已满!无法添加货物。");
}catch (Exception e) {
// TODO: handle exception
}
}
repo.add(t);
condition.signal();
}finally {
lock.unlock();
}
}
public synchronized void remove() {
try{
while(repo.size()<=0){
try{
condition.await();
System.out.println("仓库无货!无法从仓库取货");
}catch (Exception e) {
// TODO: handle exception
}
}
repo.remove(0);
condition.signal();
}finally {
lock.unlock();
}
}

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

  • 什么是线程安全:

    如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

  •  

Q6.选做:实验总结
 6.1 4-8(CountDownLatch)实验总结

  • 创建等待的CountDownLatch对象,因为CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,所以CountDownLatch Latch=new CountDownLatch(n);。然后调用Executors.newFixedThreadPool();创建固定线程数的线程池。
  • countDown()方法,计数器减1,如果计数器没有达0,那么await()方法会阻塞程序继续执行,latch.await();可以让主线程等待子线程的结束。

3. PTA实验总结及码云上代码提交记录

3.1本周Commit历史截图

3.2PTA实验

201521044091 《Java程序设计》第11周学习总结的更多相关文章

  1. 201521123045 <java程序设计>第11周学习总结

    201521123045 <java程序设计>第11周学习总结 1. 本周学习总结 2. 书面作业 2. 书面作业 Q1.1.互斥访问与同步访问完成题集4-4(互斥访问)与4-5(同步访问 ...

  2. 201521123027 <java程序设计>第11周学习总结

    1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2.书面作业 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用synchro ...

  3. 2018面向对象程序设计(Java)第11周学习指导及要求

    2018面向对象程序设计(Java)第11周学习指导及要求 (2018.11.8-2018.11.11)   学习目标 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API: ...

  4. 面向对象程序设计(JAVA) 第11周学习指导及要求

    2019面向对象程序设计(Java)第11周学习指导及要求 (2019.11.8-2018.11.11)   学习目标 理解泛型概念: 掌握泛型类的定义与使用: 掌握泛型方法的声明与使用: 掌握泛型接 ...

  5. 20145236 《Java程序设计》第九周学习总结

    20145236 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章 整合数据库 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API ...

  6. 2018-2019 2 20175230《Java程序设计》第九周学习总结

    <Java程序设计>第九周学习总结 主要内容 MySQL数据库管理系统 1.下载 2.安装 启动MySQL数据库服务器 1.启动 2.root用户 MySQL客户端管理工具 建立连接 建立 ...

  7. 20175209 《Java程序设计》第九周学习总结

    20175209 <Java程序设计>第九周学习总结 一.教材知识点总结 有关数据库下载中存在可能出现的问题已经在博客<数据库安装和使用过程中出现的一些问题>给出了相应的解决办 ...

  8. 20175208 《Java程序设计》第九周学习总结

    20175208 2018-2019-2 <Java程序设计>第九周学习总结 一.教材学习内容总结: 第11章 JDBC与MySQL数据库 MySQL数据库管理系统 MySQL数据库管理系 ...

  9. 20175202 《Java程序设计》第九周学习总结

    20175202 2018-2019-2 <Java程序设计>第九周学习总结 教材知识点总结 第11章 JDBC与MySQL数据库 MySQL数据库管理系统 MySQL数据库管理系统,简称 ...

  10. 20175227张雪莹 2018-2019-2 《Java程序设计》第九周学习总结

    20175227张雪莹 2018-2019-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十一章 JDBC数据库操作 MySQL数据库管理系统 下载安装MySQL 若下载的是 ...

随机推荐

  1. CentOS 7 服务器配置--安装CentOS 7

    看博客园也有几年的时间了,这是第一次鼓足勇气发一下我自己的博客,不为了别的,只是最近打算学习Linux的服务器配置,就写几篇博文把我学的一点点的记录下来,方便以后自己回顾学习. 今天就先记录下我安装C ...

  2. Windows Graphics Programming Win32 GDI and DirectDraw第六章疑问

    <Windows Graphics Programming Win32 GDI and DirectDraw>6.1节中有这样的描述: The Windows NT/2000 graphi ...

  3. Maven详解(三)------ Maven工程目录介绍

    上一章我们配置并安装好了 Maven,那么这一章我们介绍如何用eclipse创建一个 Maven 工程,然后介绍 Maven 工程的目录结构. 1.eclipse 创建 Maven 工程 第一步:Fi ...

  4. js与php的区别

     1 . PHP拼字符串用的是点.         js用+号.2.  php文件要放在wamp文件里面的www里面.3.  php与js的嵌入方式相同,只是嵌入的标记不一样.4.  php输出语法用 ...

  5. ReactiveSwift源码解析(十二) MutableProperty基本代码实现

    前两篇博客我们分别聊了ReactiveSwift框架中的负责标记对象的生命周期的类Lifetime以及负责原子性操作的Atomic类的具体代码实现.前两篇博客之所以聊Lifetime以及Atomic的 ...

  6. VMware Workstation 12 Pro 之安装林耐斯StartOS X64系统

    VMware Workstation 12 Pro 之安装林耐斯StartOS X64系统... ---------------- 先去下载系统暗中包ISO   网址:http://www.xiaza ...

  7. MySQL57安装教程

    MySQL57安装教程... --------------------------- 首先需要下载MySQL57安装包: --------------------------------------- ...

  8. Nginx入门案例(Mac版)

    Nginx(engine x)是一个轻量级.高性能的Web和反向代理服务器,也是一个IMAP.POP3和SMTP服务器,并且安装十分简单,配置文件非常简洁,启动特别容易,运行十分稳定,几乎可以做到7* ...

  9. 【JBoss】数据库连接配置小结(转)

    数据库驱动位置: %JBOSS_HOME%\server\default\lib目录下. 数据库配置文件位置:JBOSS_HOME\docs\examples\jca\XXXX-ds.xml < ...

  10. tensorflow安装调试总结(持续更新)

    这段时间需要部署tensorflow到linux上,由于堡垒机不能连外网,所以pip.apt-get.wget.git统统不能用,然后就是各种调试了,下面整理了一些遇到的问题和解决方案,供大家参考(C ...