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源代码使其可以同步访问。(关键代码截图,需出现学号)

//201521123013
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)
exec.shutdown();
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);
notifyAll();
}
public synchronized void remove() {
while(repo.size()<=0){
try{
wait();
System.out.println("仓库无货!无法从仓库取货");
}catch (Exception e) {
// TODO: handle exception
}
}
repo.remove(0);
notifyAll();
}

 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.查询资料回答:什么是线程安全?(用自己的话与代码总结,写自己看的懂的作业)

  • 什么是线程安全:

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

  • 也就是当多个线程访问同一资源时才有线程安全的问题,我们要保证每次运行的结果跟单线程运行结果一样,就必须保证其在对共享资源进行操作的时候不被打扰,这就需要用到synchronized关键字,通过让访问共享资源的线程获得对象锁以获得操作权,而其他线程处于等待中。
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; //最后获得的id才会为0,线程安全
}
}

Q6.选做:实验总结

 6.1 4-8(CountDownLatch)实验总结

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

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

  • Collections.synchronizedList(new ArrayList<Integer>());

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


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

3.1本周Commit历史截图

3.2PTA实验

201521123013 《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. Windows开发笔记-错误处理

    Windows函数为开发者提供了错误代码,这样当调用Windows函数失败后,可以通过查看错误代码了解错误信息.相应的错误与主调线程关联在一起,这种机制使得不同的线程能够独立运行而不会相互干扰.调用G ...

  2. JMeter之Throughput Controller详解(实验)

    Throughput Contoller,直译是吞吐量控制器,它是用来控制该控制器下面元件的执行次数,与控制吞吐量的功能无关.(注:用Constant Throughput Timer可以控制吞吐量. ...

  3. Entity Framework入门教程:Oracle数据源访问

    由于System.Data.OracleClient.dll从.NET Framework4.0之后已被弃用,所以我们无法在.NET Framework高版本中使用.一番搜索之后,发现好多文章提到.N ...

  4. Node.js之包与npm包管理工具

    Node.js之包与npm包管理工具 1.Node.js中的包 1.1在一个包中包含如下内容: package.json:对包进行描述 在bin子目录中存放二进制文件 在lib子目录中存放JavaSc ...

  5. git命令中带有特殊符号如@

    使用带用户密码clone的方式:git clone https://username:password@remote 当username和password中含有特殊符号会导致出错,因为为http的请求 ...

  6. hadoop系列四:mapreduce的使用(二)

    转载请在页首明显处注明作者与出处 一:说明 此为大数据系列的一些博文,有空的话会陆续更新,包含大数据的一些内容,如hadoop,spark,storm,机器学习等. 当前使用的hadoop版本为2.6 ...

  7. Java WEB工程搭建UEditor

    1. ueditor简介: UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码... UEdito ...

  8. hdu 6133---Army Formations(启发式合并+树状数组)

    题目链接 Problem Description > Stormtroopers were the assault/policing troops of the Galactic Empire. ...

  9. Struts2.5 利用Ajax将json数据传值到JSP

    AJAX +JSON=>JSP AJAX AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着 ...

  10. 使用php下载的文件打不开,自己用着没问题,客户用就不行?

    1 现象: 开发的时候用的好好的文件下载功能,部署到客户那边就不好使了,几乎所有从服务器下载下来的文件都不能打开. 比较了上传前的文件.上传后服务器端的文件.下载后本机的文件,发现同一个文件,上传后还 ...