GYM是葛一鸣老师的简写。GYM系列文章都是观看葛老师课程的个人笔记。
线程的优势
1.发挥多处理器的强大能力
2.代码责任单一,方便调试
3.异步事件的简化处理,防止客户端阻塞
4.响应更灵敏的用户界面
多线程危害
1.线程安全性可能是非常复杂的,线程执行顺序是不可预测的,竞争条件,脏读。
2.活跃性问题:某件正确的事情最终会发生,死锁。
3.性能问题:context Switch 切换、影响性能。
java线程状态
1.New:状态 已经分配内存,无cpu时间
2.Runable: 资源已经全部分配,可能在已经分配cpu时间
3.blocked:进入临界区,被挂起
4.waiting:等他其他线程唤醒,或者定时唤醒
5.terminated:终止状态
x\
java线程的操作
- Thread的start()在新的线程中调用run()方法,单纯吊用run()方法不会开启一个新的线程。
- 两种方法新建:
(1)传递一个实现Runable的类;
(2)重载Thread的run()方法; - 每个线程都拥有自己的名字;
终止线程
- thread.stop() 不建议使用,过于暴力,直接终止,可能导致数据的不一致,。
- thread.interruput() 中断线程,只是给相应的线程打招呼,并不会真的终端线程
- thread.isInterruput() 判断线程是否被中断,采取相应的措施
- thread.sleep() InterruptedException
在sleep过程中其他线程发送中断请求 ,可以在catch中做出中断处理。
中断异常的时候清空中断标志位,catch中需要重新设置中断标志,while中使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26static class InterruptedThread implements Runnable {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("i am breaking");
break;
}
try {
System.out.println("i want to sleep");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("someone interrupt me");
//恢复中断标志位
Thread.currentThread().interrupt();
}
}
}
}
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(new InterruptedThread(), "t1");
thread.start();
Thread.sleep(7000);
thread.interrupt();
}
输出结果:1
2
3
4i want to sleep
i want to sleep
someone interrupt me
i am breaking
六、线程挂起和继续执行
不建议使用,resume()发生在suspend之前时,线程无法释放锁处于runnable转台
- tread.suspend() 占用锁不释放
- thread.resume() 重启线程
七、等待和谦让(debugger、测试可能使用)
- thread.yield() 释放当前线程的cpu时间,但是还是继续竞争,
- thread.join()等待线程结束
调用线程等待join函数的所属线程结束join实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
守护线程
在后台默默完成一些系统性的服务,如GC、JIT理解为守护线程
setDeamon();在start之前设置
如果没有业务线程守护线程也会死掉。
线程优先级
setPriority(Thread.MAX_PRORITY)
高优先级程序不一定就能一直抢占cpu时间,只是几率高一些
线程同步
- synchronized
(1)指定加锁对象
(2)修饰实例方法:相当于当前对象加锁
(3)直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁 - object.wait()、object.notify()、notifyAll()
没有获得监视器之前不能使用wait(),会释放当前线程的监视器,通知其他线程执行; notify之后不会立即启动wait方法,拿到锁之后可以继续执行wait之后的事情。唤醒所有等待监视器的线程中的其中一个线程。notifyAll唤醒所有的线程,去争用监视器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31public static Boolean flag = true;
public static class Task implements Runnable {
@Override
public void run() {
try {
//必须获取监视器才能用wait 会排数InterruptedException
synchronized (flag) {
System.out.println("im ready to wait");
flag.wait();
System.out.println("someone notify me");
}
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args) throws Exception {
new Thread(new Task()).start();
Thread.sleep(5000);
synchronized (flag) {
TestWaitNotify.flag.notifyAll();
}
}
输出结果
/**
*im ready to wait
*someone notify me
*/