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. 你不可错过的二维码生成与解析-java后台与前端js都有

    1.二维码分类   二维条码也有许多不同的码制,就码制的编码原理而言,通常分为三种类型. 线性堆叠式二维码 编码原理: 建立在一维条码基础之上,按需要堆积成两行或多行. 图示: 矩阵式二维码 最常用编 ...

  2. JavaWeb三大组件之一Filter知识总结

    [1] Filter简介    > Filter翻译为中文是过滤器的意思.    > Filter是JavaWeb的三大web组件之一Servlet.Filter.Listener    ...

  3. Java自定义注解及使用

    本文通过一个简单的例子展示注解的工作原理. 1.声明注解类型 @Target(value = ElementType.METHOD) //声明该注解的运行目标: 方法 @Retention(value ...

  4. python中的collections.namedtuple

    简介 collections.namedtuple是一个工厂方法,它可以动态的创建一个继承tuple的子类.跟tuple相比,返回的子类可以使用名称来访问元素. 使用方法 用一个例子来介绍: > ...

  5. python+selenium自动化软件测试(第7章):Page Object模式

    什么是Page ObjectModel模式Page Objects是selenium的一种测试设计模式,主要将每个页面看作是一个class.class的内容主要包括属性和方法,属性不难理解,就是这个页 ...

  6. 2017面向对象程序设计(Java)第二周学习总结

    2017面向对象程序设计(Java)第二周学习总结 直系学妹学弟们好!额...不要问我为什么把学妹放前面,我也不知道!我只是你们和蔼可亲的学长一枚而已.也不要问为什么是第二周学习总结而不是第一周,因为 ...

  7. anaconda安装加速镜像问题解决

    Anaconda使用conda连接网络出现错误 我使用的是windows10 64bit下的Anaconda2,在安装和更新包的时候出现以下报错信息. 这是使用默认源安装包的报错信息: C:Users ...

  8. JAVA_多线程_单例模式

    这篇是入职之后的第二篇了,上一篇我简单介绍了一下LOCK里面的类的方法,感兴趣的话可以去了解一下,以后坚持每周至少会更新一篇关于多线程方面的文章,希望博友们可以一起加油成长. 这篇主要的内容是单例模式 ...

  9. TC358749XBG:HDMI转MIPI CSI芯片简介

    TC358749XBG是一颗HDMI转MIPI CSI功能的视频转换芯片,分辨率:1920*1080,电源3.3/1.8/1.2,通信方式:IIC,封装形式BGA80

  10. QT creator编程C++第一步,说“Hello world!”

    这个学期选了计算机学院的<数字图像处理>,正好和我的图像识别项目有所关联,老师说不能用MATLAB来做,这让我一个没学过C++的孩纸欲哭无泪. 只好求助计算机学院的大佬,自学C++. 大佬 ...