每天几条java(5)

Question: 16
Given:
1. public class TestSeven extends Thread {
2. private static int x;
3. public synchronized void doThings() {
4. int current = x;
5. current++;
6. x = current;
7. }
8. public void run() {
9. doThings();
10. }
11.}
Which statement is true?
A. Compilation fails.
B. An exception is thrown at runtime.
C. Synchronizing the run() method would make the class thread-safe.
D. The data in variable "x" are protected from concurrent access problems.
E. Declaring the doThings() method as static would make the class thread-safe.
F. Wrapping the statements within doThings() in a synchronized(new Object()) { } block would make the class thread-safe.

Answer: E

这题做不出来,谷歌一下,整理好再写上来好了。

题解:首先有过多线程编程的都不难看出这个程序是没有语法上的错误的。也不会有exception,AB错误。

C是没有用的,因为首先dothings()是在每个对象里面的,而且已经声明同步,说一在run()声明同步没用。F也同理可知not help

 D

因为xstatic的,所以是被所有TestSeven对象共享的,所以多个线程对象TestSeven执行doThings方法时,虽然这个方法是synchronized的,但是锁对象是this,所以说一个线程对象的doThings方法中更改了x,在另一个线程对象却可以得到他本身的锁标记而执行doThings方法,但其中x被更改,就存在了安全问题。

把方法也换成static后可保证线程安全

例如:

调用doThings后,x=2

但是在线程还没有执行1的时候,该线程的时间片段用完,cup交给另一个线程t2

t2也执行doThings()一次,把x修改成2,然后继续回到t1线程中,t1doThings继续执行,执行完后,x=3,而不是2,出现了问题

   普通同步方法锁定的是与 this 相关联的监视器;而静态同步方法则是与包含该方法的类所对应的 Class 对象相关联的监视器;

所以说每个静态方法的锁对象都是相同的,因此不会出现上面那种不安全的因素,E正确。

 

 



Question: 17
Given:
1. public class Threads3 implements Runnable {
2. public void run() {
3. System.out.print("running");
4. }
5. public static void main(String[] args) {
6. Thread t = new Thread(new Threads3());
7. t.run();
8. t.run();
9. t.start();
10. }
11. }
What is the result?
A. Compilation fails.
B. An exception is thrown at runtime.
C. The code executes and prints "running".
D. The code executes and prints "runningrunning".
E. The code executes and prints "runningrunningrunning".

Answer: E

明显是E,呃……不解释,没什么好解释的。

 



Question: 18
Given:
public class NamedCounter {
private final String name;
private int count;
public NamedCounter(String name) { this.name = name; }
public String getName() { return name; }
public void increment() { count++; }
public int getCount() { return count; }
public void reset() { count = 0; }
}
Which three changes should be made to adapt this class to be used safely by multiple threads? (Choose three.)
A. declare reset() using the synchronized keyword
B. declare getName() using the synchronized keyword
C. declare getCount() using the synchronized keyword
D. declare the constructor using the synchronized keyword
E. declare increment() using the synchronized keyword

Answer: A, C, E

题解:

构造方法不能用 synchronized 声明,也没必要声明,构造只用一次;

B getName 也没必要,因为namefinal,不能更改,不用担心并发;

ACE 3个方法都共同访问一个变量count ,在多线程访问同一个变量,要做同步。

 



Question: 19
Given:
7. void waitForSignal() {
8. Object obj = new Object();
9. synchronized (Thread.currentThread()) {
10. obj.wait();
11. obj.notify();
12. }
13. }
Which statement is true?
A. This code may throw an InterruptedException.
B. This code may throw an IllegalStateException.
C. This code may throw a TimeoutException after ten minutes.
D. This code will not compile unless "obj.wait()" is replaced with "((Thread) obj).wait()".
E. Reversing the order of obj.wait() and obj.notify() may cause this method to complete normally.
F. A call to notify() or notifyAll() from another thread may cause this method to complete normally.

Answer: B

wait方法使用的前提是要取得调用wait方法的对象的对象锁。

而本代码取的是Thread.currentThread()的对象锁,造成错位。

你可以试试将obj.wait()改成Thread.currentThread().wait()

或者synchronized (Thread.currentThread()) 改成synchronized (obj) 

这样对象锁和wait方法的对象保持一致就不会出错。

同时为什么notify相关的那几个选项会错呢?因为notifynotifyallwait都是在对象同步块进行使用的。

"只能由持有对像锁的线程来调用"说明wait方法与notify方法必须在同步块内执行,synchronized(obj)之内.再者synchronized代码块内没有锁是寸步不行的,所以线程要继续执行必须获得锁。相辅相成。(51CTOblog——天下无贼)

也就是说跟上面wait一样,对象锁问题造成错位!——EF

既然已经说明了为什么编译不成功,那么说明无法运行:C错。

Obj不能转ThreadD错。

A为阻塞,很明显,都错位了,还不到阻塞的阶段。A错。

 

 

 



Question: 20
Which two code fragments will execute the method doStuff() in a separate
thread? (Choose two.)
A. new Thread() {
public void run() { doStuff(); }
};
B. new Thread() {
public void start() { doStuff(); }
};
C. new Thread() {
public void start() { doStuff(); }
}.run();
D. new Thread() {
public void run() { doStuff(); }
}.start();
E. new Thread(new Runnable() {
public void run() { doStuff(); }
}).run();
F. new Thread(new Runnable() {
public void run() { doStuff(); }
}).start();

Answer: D, F

 

考察点1start(),run()

Thread类中run()start()方法的区别如下:

run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用;

start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;

那么C错误,E也因为不是调用start()方法启动线程所以错误,AB没有启动线程,错误。

因为Runnable是个接口,为了简单一些,我们有时候会用匿名类来实现相同的功能。

即类似F,当然也可以在new一个thread再进行thread.start()

 

 

转载于:https://www.cnblogs.com/m1s4nthr0pezy/p/3673506.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值