JAVA多线程 总结
1. Thread 和 Runnable
java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承 java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。
因为Java不支持多重继承,因此普遍推荐调用接口实现
用Runnable与Callable接口的方式创建多线程的特点:
- 线程类只是实现了Runnable接口或Callable接口,还可以继承其它类。
- 在这种方式下,多个线程可以共享一个target对象,所以非常适合多个线程来处理同一份资源情况。
- 如果需要访问当前线程,需要使用Thread.currentThread方法。
- Callable接口与Runnable接口相比,只是Callable接口可以返回值而已。
用Thread类的方式创建多线程的特点:
- 因为线程已经继承Thread类,所以不可以再继承其它类。
- 如果需要访问当前线程,直接使用this即可。
1. Sleep()和Wait()
sleep()方法是Thread类里面的,主要的意义就是让当前线程停止执行,让出cpu给其他的线程,但是不会释放对象锁资源以及监控的状态,当指定的时间到了之后又会自动恢复运行状态。
wait()方法是Object类里面的,主要的意义就是让线程放弃当前的对象的锁,进入等待此对象的等待锁定池,只有针对此对象调动notify方法后本线程才能够进入对象锁定池,进入准备状态,准备获取对象锁进入运行状态。
notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。
1) 使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
2)sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。
2. 线程和进程
- 一个进程是不是可以创建无限数量的线程
-
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆 栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。
在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一 个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
- 线程的数量会受到什么限制
- 线程在内存中会占用什么资源
3. 常见的线程安全集合的记忆方法
Vector, Stack, Hashtable, Enum
4. 死锁的必要条件
占有和等待条件:已经得到某个资源的进程可以再请求新的资源
不可抢占条件:已经分配给一个进程的资源不能被强制性地抢占,它只能被占有它的进程显示地释放
环路等待条件:死锁发生时,系统中一定有由两个或两个以上的进程组成一个环路,该环路中每个进程都在等待下一个进程所占有的资源