sleep:让线程睡眠指定时间, 会释放cpu时间片
join: 本质是wait/notify, 让线程的执行结果可见
yiled 让出时间片.触发重新调度.; 作用效果和sleep(0)一样,触发一次切换
2.wait和sleep的区别
sleep()方法是Thread类的静态方法,是线程用来控制自身流程的,他会使此线程暂停执行一段时间,而把执行机会让给其他线程,等到计时时间一到,此线程会自动苏醒.而wait()方法是object类的方法,用于线程间通信,这个方法会使当前拥有该对象锁的进程等待,直到其他线程调用notify()方法或者notifyAll()时才醒来,不过开发人员也可以给他指定一个时间,自动醒来。
对锁的 处理机制不同。由于sleep()方法的主要作用是让线程暂停执行一段时间,时间一到则自动恢复,不涉及线程间的通信,因此,调用sleep()方法并不会释放锁。而wait()方法则不同,当调用wait()方法后,线程会释放掉他所占用的锁,从而使线程所在对象中的其他synchronized数据可以被其他线程使用。
使用区域不同。wait()方法必须放在同步控制方法和同步代码块中使用,sleep()方法则可以放在任何地方使用。sleep()方法必须捕获异常,而wait()、notify()、notifyAll()不需要捕获异常。在sleep的过程中,有可能被其他对象调用他的interrupt(),产生InterruptedException。由于sleep不会释放锁标志,容易导致死锁问题的发生,因此一般情况下,推荐使用wait()方法\
2.线程通信的几种方式
一、 使用同一个共享变量控制: Synchronized、join(wait、notify) wait、notify、Lock、Condition 利用volatile 利用AtomicInteger
二、PipedInputStream、PipedOutputStream
三、利用BlockingQueue
四、利用LockSupport---->park()和unpark(thread)
五、利用ThreadLocal
2、Java中能够创建volatile数组吗?
可以创建, Volatile 对于引用可见,对于数组中的元素不具备可见性。
3、++操作是线程安全的吗?
不是线程安全的, 原子性、有序性、可见性。++操作无法满足原子性
4、线程什么时候会抛出InterruptedException()
t.interrupt() 去中断一个处于阻塞状态下的线程时(join/sleep/wait)
5、Java 中Runnable和Callable有什么相同和区别
相同点:1)都是接口;2)都可以编写多线程程序;3)都采用Thread.start()启动线程
不同点:1)Runnable没有返回值;Callable可以返回执行结果,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果
2)Callable接口的call()方法允许抛出异常;Runnable的run()方法异常只能在内部消化,不能往上继续抛
注:Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞
7. 有T1/T2/T3三个线程,如何确保他们的执行顺序
方法一: 在主线程中直接通过 join() 调用
方法二:先启动最后一个T3,然后T3中调用T2,T2中调用T1
8.Java内存模型是什么?
JMM是一个抽象的内存模型。它定义了共享内存中多线程程序读写操作的行为规范:在虚拟机中把共享变量存储到内存以及从内 存中取出共享变量的底层实现细节。通过这些规则来规范对内存的读写操作从而保证指令的正确性,它解决了CPU多级缓存、处理器优化、指令重排序导致的内存访问问题,保证了并发场景下的 可见性。
9.什么是线程安全
原子性、有序性、可见性(硬件层面(CPU高速缓存、指令重排序、JMM))
10 死锁
条件:1、互斥条件 2、请求与维持 3、不掠夺 4、循环等待
11.hashtable
hashtable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低.
12.ConcurrentHashMap
1).是 J.U.C 包里面提供的一个线程安全并且高效的 HashMap
2)在 JDK1.7由一个个 Segment 组成,通过继承 ReentrantLock 来进行加锁,采用的分段锁,通过每次锁住一个 segment 来保证每个segment 内的操作的线程安全性。每个segment 都有一个hashEntry[] ,冲突健进行链式分布。
3)JDK1.8 相比于 1.7 版本,它做了两个改进
为什么要引入红黑树呢?
在正常情况下,key hash 之后如果能够很均匀的分散在数组中,那么table 数组中的每个队列的长度主要为 0 或者 1.但是实际情况下,还是会存在一些队列长度过长的情况。如果还采用单向列表方式,那么查询某个节点的时间复杂度就变为 O(n); 因此对于队列长度超过 8 的列表,JDK1.8 采用了红黑树的结构,那么查询的时间复杂度就会降低到O(logN),可以提升查找的性能;