问题记录

是的,FutureTask是依靠其内部类java.util.concurrent.FutureTask.Sync<V>类来实现阻塞。Sync又是实现了AbstractQueuedSynchronizer类。

ConcurrentHashMap怎么实现线程安全(1.7和1.8),和HashTable的区别?
ConcurrenthashMap底层是segment数组,一个segment就是一个子哈希表,与hashtable几乎全用syn加锁不同,con在操作的时候是对segment块进行加锁。
put是调用segment中的put方法,get中涉及到的变量不用加锁,因为都用volatile修饰过了。

线程池的底层工作原理、饱和策略
当提交新任务到线程池时,发生:
判断核心线程池中线程是否都在执行任务,如果不是则新建一个核心线程执行任务,如果线程都在工作,
判断工作队列是否已经满了,如果没满,则将新任务放到工作队列中,如果满了
判断线程池中的线程数量是否已满,如果没满新建一个普通线程执行任务,如果满了,执行饱和策略
饱和策略:直接抛出异常+丢弃任务队列中一个任务,然后执行新任务+不处理,丢弃掉

i++和i=i+1的区别(我只说了赋值顺序不同,后面面试官提醒后面的形式能强转类型前面的那种不能)1++是原子操作吗?

i++不是原子操作;
其执行要分为3步:1、读内存到寄存器;2、在寄存器中自增;3、写回内存

内部类和静态内部类区别

相同点:

使用的时候,import的时候,除了包名,还要带外部类。

不同点:

对象创建的方式不同

静态内部类创建对象的时候,独立于外部类及其对象,就好像它是一个独立的类,可以和外部类一样使用。

内部类创建对象的时候,不能独立于外部类,必须要先创建外部类的对象,然后再用这个对象来new出内部类的对象。

说一下序列化,网络传输使用什么序列化
还是字符 字节,如果是socket,将OutputStream传入socket流,然后用write/read方法

说一下泛型底层实现原理—类型擦除
Java的泛型类型擦除是发生在编译时的,在编译时会擦除泛型的参数来化类型,并检查相应的代码,同时在相应的地方插入强源制转换的代码。
简单的说就是,类型参数只存在于编译期,在运行时,Java 的虚拟机 ( JVM ) 并不知道泛型的存在。
可以用extend规定参数类型边界。

说一下JUC包下的同步工具
java.util.concurrent(简称JUC)包

JUC提供的一些实现:

    Atomic : AtomicInteger  原子操作类

    Locks : Lock, Condition, ReadWriteLock  可重入读写锁

    Collections : Queue, ConcurrentMap 并发集合

    Executer : Future, Callable, Executor 线程执行池,异步Future等

    Tools : CountDownLatch, CyclicBarrier, Semaphore 减数器,等待器,信号量


volatile如何怎么保证有序性和可见性
可见性实现原理:每个处理器通过检查在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。
有序性实现原理:volatile可以禁止指令重排,这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。被volatile修饰的变量的操作,会严格按照代码顺序执行

任务类型?如果提交一个cpu密集型的任务怎么选取线程池
任务类型分两种:CPU密集型和IO密集型,
cpu密集型是对cpu的请求大于cpu核心数量,线程数量设置多了也没有用
io密集型是对io的请求较大,为了防止cpu长时间等待,应该增加线程数量

线程的几种状态,并指出在哪种状态下可以中断,中断原理
新建-就绪-运行-等待-超时等待-阻塞-死亡
除了新建和死亡状态都可以中断,设置标记位或者调用interrupt()方法,之前还有stop方法但已弃用
原理:每个线程对象里都有一个boolean类型的标识,代表着是否有中断请求,interrupt方法可以修改这个标记位

手写一个生产者消费者模式

ReentrantLock加锁操作后,在catch中捕获的是什么异常,为什么会发生这用异常



Java数据类型有哪些? 除了基本数据类型,引用类型有数组+类+接口

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务