Java 多线程
1. 进程和线程区别:
进程通常是代表一个应用程序,进程中包含一个以上线程;
系统会为进程分配独立的内存资源,其中线程可以共享进程中的资源,线程也有自己的少量资源空间(如程序计数器,一组寄存器和栈);
线程是系统CPU调度的基本单位;
2. 创建与启动的两种方式:
// a.继承Thread方法,重写run()方法 new Thread(){ public void run(){ } }.start(); //b.实现Runnable接口,重写run()方法,再传入Thread。 new Thread(new Runnable(){ public viod run(){ } } ).start(); //区别:Thread本身实现了Runnable接口,第一种方便,第二种使用更灵活。
3. 几种状态:5种
新建:new完,没有start;
就绪:等待CPU;
运行:正在运行,使用CPU;
阻塞:三种(wait池,锁池,其它:sleep / join / IO);
死亡:执行正常完成,遇到异常结束;
4. 调度相关:
sleep()
wait notify notifyAll():通常会结合 if 判断使用
yield()
join()
interrupte()
5、sleep() wait() 区别,及yield()方法;
(1)所属类:wait()是Object中的方法,使当前线程进行锁池;sleep()是Thread中的静态方法,使当前线程挂起一段时间;两者都会造成阻塞;
(2)锁:sleep只是让当前线程让出cpu给其他线程,不会释放对象锁;wait是进入对象的 wait pool池中,会释放对象锁。
(3)使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
-
synchronized(x){
x.notify()
//或者wait()
}两者相同点:都需要捕获InterruptedException异常。
yield(),Thread的静态方法,短暂让出cpu,让 相同优先级 或 更高优先级 的线程获得运行机会,一般调试时才用。
6、线程调度:
有两种线程调度方式:分时调度模型、抢占式调度模式;
Java使用的是抢占式调度,使一个线程一直运行,直到它不得不放弃CPU资源(yield,阻塞,运行完成);
如果希望一个线程给另一个线程运行机会有以下几种方式:
a. 调整各个线程优先级;
b. 调用Thread.sleep();
c. 调用Thread.yield();
d. 调用另一个线程的join()方法;
7、守护进程:
也称后台进程,是指为其它线程提供服务的线程;如Java的GC线程,负责回收其它线程不再使用的内存;
特点:后台线程与前台线程相伴运行,只有当所有前台线程结束生命周期后,后台线程才会结束生命周期。
需在线程start() 启动前调用 someThread.setDaemon(true); 由后台线程启动的线程默认也是后台线程;
8、同步 synchronized:
// 1、同步一段代码 public class mytest { private String mLock; public void lockedMethod(){ //... synchronized (mLock){ //... } } } ------------------------------ // 2、同步一个方法 public synchronized void lockedMethod() { } 等价于: synchronized (this) { //... } ------------------------------ // 3、保护类方法 public synchronized static void lockedMethod() { } 等价于: public static void lockedMethod() { synchronized (mytest.class){ //... } } //以上锁的作用范围逐渐扩大。
释放锁:
a. 执行完同步代码块;
b. 遇到异常;
c. 线程执行过程中,执行了对象的wait()方法,放入对应对象的wait pool;
以下情况不会释放锁:
a. Thread.sleep()方法;
b. Thread.yield()方法;
线程间通信:
wait(); notify();
中断阻塞:
someThread.interrupt();
可使从wait lock 和 other lock(sleep,join,IO)中解放出来;
9、线程控制:
start();
suspend(); //一个线程调用另一个线程的这个方法,而不恢复,会直接造成死锁;
resume();
stop(); // 会使一个线程执行到原子操作中间的不正常状态;
JDK 1.2 后三者已弃用;
用代码优雅的实现线程控制:
SUSP: 暂停状态,使线程进入当前线程对象的等待池;
STOP: 终止状态,线程自然退出run();
RUN: 运行状态,线程可以继续运行;