JAVA2015086第十一周作业
- 本周学习总结
1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容。
- 书面作业
本次PTA作业题集多线程
1.互斥访问与同步访问
完成题集4-4(互斥访问)与4-5(同步访问)
1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步访问(请出现相关代码)?
还可以使用Lock对象和Condition对象实现互斥同步访问。
public void deposit(int money) {
lock.lock();
try {
this.balance = getBalance() + money;
} finally {
lock.unlock();
}
}
public synchronized void withdraw(int money) {
lock.lock();
this.balance = getBalance() - money;
try {
try {
if (balance < 0) {
condition.await();
}
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
if (balance < 0) {
throw new IllegalStateException(balance + "");
}
} finally {
lock.unlock();
}
}
1.2 同步代码块与同步方法有何区别?
主要是格式上的不同,同步代码块主要是在方法中使用synchronized关键字实现互斥public void 方法名{ synchronized(类对象名T) {//同步代码块} };同步方法是在定义方法时,加在void前,public synchronized void 方法名{//同步代码块}
1.3 实现互斥访问的原理是什么?请使用对象锁概念并结合相应的代码块进行说明。当程序执行synchronized同步代码块或者同步方法时,线程的状态是怎么变化的?
①需要实现互斥访问的原因是有时两个或两个以上的线程需要同时对同一资源存取,而线程之间如果不加以控制,会产生一种情况-竞争;线程对该资源进行操作时即上锁,这样其他同步线程就无法获取资源,等执行中的线程结束之后,释放资源,让其他线程继续争取对资源的使用权。
②关于对象锁:每个对象都有一把锁,如果未获得对象锁,下面的代码就无法执行,必须等待。从而通过对象锁实现了互斥访问。
class MyCounter{
private int i = 0;
public void increment(){
synchronized (this) {//获得this这个对象上的内部锁
i++;
}
}
}
③假设线程A与线程B同时争取同一个资源,当A和B同时获取CPU进入Running之后,只能有一个线程(假设为A)获得资源的使用权,那么A线程就能进入LockPool获取同步锁继续执行,结束后将同步锁释放出来,而B就要进入WaitPool(通过wait();)等待同步锁被释放后进入LockPool(通过notify();/notifyAll();)重新争取同步锁。
如果有多个线程,则每次只有其中的一个线程获得对象锁,进入addId()、substractId()方法,执行id++、id--。直到该方法结束,同步锁被释放,下一个线程才能获得对象锁。
1.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作?为什么同步访问一般都要放到synchronized方法或者代码块中?
wait()和notify()/nofityAll()来实现线程之间的通信;存在多个线程同时运行时,没有互斥,将会使线程运行混乱,例如存钱与取钱,可能有多个人要进行,若是synchronized关键字,存钱时与取钱时,可能会造成A存钱时,B存钱也同时进行,而C取钱,余额在A,B,C的操作下同时进行,数值将会错误
2.交替执行
实验总结(不管有没有做出来)
实验总结:先是建立Repo类,存储字符串items.split(" ");;Worker1和Worker2类继承Runnable接口,若是要两个线程交替运行,需要使用wait()和notify()函数,需要在run函数加入synchronized关键字,run函数中循环while(),循环条件是this.repo.getSize()!=0,输出字符串数组,并将null该字符串数组,达到将任务删除,通过判断数组下标的奇偶数来决定接下来需要运行的线程,若是偶数,则运行Worker1,Worker2则wait();若是奇数则运行Worker2,Worker1则wait();以此来交替线程运行;题目的难点在于怎么样设计这个两个线程的交替实现,由于线程争用cpu的随机性,就需要Worker1和Worker2线程执行,在Worker1执行完一次进入等待之前唤醒Worker2,如此往复,主要要用上wait()和notify()了。
3.1
修改TestUnSynchronizedThread.java源代码使其可以同步访问。(关键代码截图,需出现学号)**
//201521123086
public static synchronized void addId() {
id++;
}
public static synchronized void subtractId() {
id--;
}
3.2
进一步使用执行器改进相应代码(关键代码截图,需出现学号)
//201521123086
List<Callable