Java牛客 -- 专项练习(5)

前因:

记录在牛客上刷题的错题记事本

1.在java7中,下列哪个说法是正确的:

A : ConcurrentHashMap使用synchronized关键字保证线程安全
B : HashMap实现了Collection接口
C : Arrays.asList方法返回java.util.ArrayList对象
D : SimpleDateFormat对象是线程不安全的

答案选D,

  • A、ConcurrentHashMap在JDK1.7的时候,使用Segment这个数据结构,利用锁分段技术保证了线程安全,JDK1.8的时候,Segment这个数据结构就废了,开始使用Synchronized+CAS保证线程安全。

  • B、HashMap,没有实现Collection,其实Map和Collection是集合框架中独立的两大接口。

  • C、Arrays.asList返回的也是ArrayList,不过这是个Arrays中的内部类,实现了List接口,继承了AbstractList,但是内部类中并没有重写涉及结构性变化的方法,所以一旦调用结构性变换的函数,例如add,会出现运行时异常UnsupportedOperationException。

  • D、DateFormat这个接口的实现类都是不安全的。

2. true、false、null、sizeof、goto、synchronized 哪些是Java关键字?

A : true
B : false
C : null
D : sizeof
E : goto
F : synchronized

答案选E,F。

3. 下列哪些操作会使线程释放锁资源?

A : sleep()
B : wait()
C : join()
D : yield()

答案B,C。

  • sleep()方法

在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。

sleep()使当前线程进入阻塞状态,在指定时间内不会执行。

  • wait()方法

在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。

当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。

唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。

waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

  • yield方法

暂停当前正在执行的线程对象。

yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

yield()只能使同优先级或更高优先级的线程有执行的机会。

  • join方法

等待该线程终止。

等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

4. 下面哪个行为被打断不会导致InterruptedException:()?

A : Thread.join
B : Thread.sleep
C : Object.wait
D : CyclicBarrier.await
E : Thread.suspend

答案选E。 抛InterruptedException的代表方法有:

  • java.lang.Object 类的 wait 方法
  • java.lang.Thread 类的 sleep 方法
  • java.lang.Thread 类的 join 方法

5. 运行代码,输出的结果是()

public class P {
    public static int abc = 123;
    static{
    	System.out.println("P is init");
    }
}
public class S extends P {
    static{
    	System.out.println("S is init");
    }
}
public class Test {
    public static void main(String[] args) {
    	System.out.println(S.abc);
    }
}
A : P is init<br />123
B : S is init<br />P is init<br />123
C : P is init<br />S is init<br />123
D : S is init<br />123

答案选A。 属于被动引用不会出发子类初始化

  • 子类引用父类的静态字段,只会触发子类的加载、父类的初始化,不会导致子类初始化
  • 通过数组定义来引用类,不会触发此类的初始化
  • 常量在编译阶段会进行常量优化,将常量存入调用类的常量池中, 本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
发布了15 篇原创文章 · 获赞 1 · 访问量 3126

猜你喜欢

转载自blog.csdn.net/ZeroWdd/article/details/104319626