201521123061 《Java程序设计》第十一周学习总结
1. 本周学习总结
1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容。
本周学习的是如何解决多线程访问中的互斥问题和线程间的合作问题
1.当有多个线程对同一个数据进行访问的时候如果不加以控制就会产生“冲突”。解决这种冲突的方法就是互斥访问:在程序代码块前加上synchronized,这样的代码块称为同步代码块。synchronized实现互斥访问主要是靠对象锁来实现的,代码块中每个对象都有一个对象锁,当获得对象锁的时候正常运行,没有获得对象锁则需要等待。
2.对于控制相互交互的线程之间的运行进度的问题可以利用wait()和notify()/notifyAll()方法来协调线程间的运行进度(读取)关系;wait()方法是让当前线程释放其所持有的“对象互斥锁”,进入wait队列(等待队列),notify()/notifyAll()方法的作用是唤醒(任意一个/所有)正在等待队列中等待的线程,并将它(们)移入等待同一个“对象互斥锁”的队列。
2. 书面作业
本次PTA作业题集多线程
1.互斥访问与同步访问
完成题集4-4(互斥访问)与4-5(同步访问)
1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步访问(请出现相关代码)?
还可以使用Condition条件对象来实现互斥同步访问
class Account{
private int balance;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public Account(int balance){
this.balance=balance;
}
void deposit(int money){
try{this.balance+=money;
condition.signal();}
finally{
lock.unlock();}
}
void withdraw(int money){
try{
while(this.balance - money < 0){
condition.await();
condition.signal();
}
this.balance-= money;
}catch(Exception e){
System.out.println(e);
}
finally{
lock.unlock();
}
}
1.2 同步代码块与同步方法有何区别?
同步方法是直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁,两者的加锁范围不一样,同步方法锁的范围大,同步代码块的范围小。
1.3 实现互斥访问的原理是什么?请使用对象锁概念并结合相应的代码块进行说明。当程序执行synchronized同步代码块或者同步方法时,线程的状态是怎么变化的?
-
实现互斥的原理是对象锁的应用,当一个线程拿到了同步对象锁,就正常运行,此时其他对象就需要在锁池等待队列中等待,当这个线程执行完同步代码后立即把锁还给同步对象其他在锁池中等待的线程的其中一个就可以拿到锁。
synchronized public void produce(){ setCount(getCount()+1); }
对于这段生产者的代码,当一个线程拥有了对象锁后将会正常进行加一的操作,此时其他线程处于wait状态,当这段代码执行结束,释放了对象锁,锁池中任意一个线程会抢到对象锁。
- 过程:多个线程争夺对象锁->其中一个线程得到对象锁其他线程在锁池中等待->执行代码->释放对象锁
1.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作?为什么同步访问一般都要放到synchronized方法或者代码块中?
- 通过wait(),notify()进行通信
- 如果不放在synchronized方法或代码块中不会产生同步冲突,例如多个对象同时对i++,最后i的结果肯定不是大家所想看到的
2.交替执行
实验总结
- 主要难点有两个一个是用split将字符串进行分隔放进数组
- 另一个就是定义了一个flag,根据flag为true或false进行任务的交替执行
3.互斥访问
3.1 修改TestUnSynchronizedThread.java源代码使其可以同步访问。(关键代码截图,需出现学号)
3.2 进一步使用执行器改进相应代码(关键代码截图,需出现学号)
参考资料:Java多线程之Executor、ExecutorService、Executors、Callable、Future与FutureTask
由于是批量进行任务执行所以选择invokeAll与invokeAny方法:
4.线程间的合作:生产者消费者问题
4.1 运行MyProducerConsumerTest.java。正常运行结果应该是仓库还剩0个货物。多运行几次,观察结果,并回答:结果正常吗?哪里不正常?为什么?
多次运行后发现结果不正常,并不是每次仓库都剩零个货物;因为多个线程之间没有通信
4.2 使用synchronized, wait, notify解决该问题(关键代码截图,需出现学号)
5.查询资料回答:什么是线程安全?(用自己的话与代码总结,写自己看的懂的作业)
在多线程的情况下的执行结果与每次单线程运行的结果一致,也就是多线程的运行结果与自己预期的结果相一致。线程安全意味着在多线程的环境下要进行同步控制的操作