多线程与高并发 1
synchronized 篇
进程 线程 协程/纤程(Quasur)
一个程序里不同的执行路径
public static class T1 extends Thread{
@Override
public void run(){
System.out.println("Override Theme 中的 run 方法");
}
}
// 方法一
new MyThread().start();
// 方法二
new MyThread().start();
// 方法三
new Thread(()->{
Sout("Hello World!");
})
创建线程的两种方式:
- 创建一个类,继承Thread,重写方法
- 定义一个类,实现 Runnable 接口,然后重写 run 方法
启动:
方法一:new MyThread().start();
方法二:new Thread(new MyRun()).start();
方法三:new Thread(()->{ Sout("Hello World!");})
//启动线程的三种方式:
1、从
Thread
继承2、实现
Runnable
接口3、从线程池中启动
Executors.newCachedThrad
线程的基本方法
// sleep 睡眠
Thread.sleep(500); // 毫秒
// Yield 让出一下CPU 进入等待队列(如果没有等待的则继续执行)
// 使用场景,较少
Thread.yield();
// Join
Thread T1 = new Thread(()->{
T1.join();
})
Thread T2 = new Thread(()->{
Sout("T2");
})
在T1中调用 T2.join();则执行到 join 之后,T1进入等待模式,先执行完T2之后,再返回执行T1。
常用来等待线程结束。
补充:
.stop()方法,用于结束线程的,但是太粗暴了,不建议使用。
;
.intereptor( )
唤起;
.getState()
获取线程状态。
线程的锁
- 上锁
private int count = 10;
private Object o = new Object();
public void m(){
synchronized(0){ //任何县城要执行下面的代码,则必须先拿到o
count--;
}
}
// synchronized(this) 等值于 synchronized(方法);
public class T{
private static int count = 10;
public synchronized static void m(){ // 等同于synchronized(T.class)
count --;
}
public static void mm(){
synchronized(T.class){
count--;
}
}
}
synchronized()
能不加锁就不加锁,加锁之后效率极低。
synchronized的特性
可重入性
一个方法m1
加锁,另一个方法m2
也加了锁(同一把锁),那么m1
是可以调用m2
的。
异常的锁
程序中的锁的内容出现了异常,那么该锁将被释放。
synchronized 底层实现
早期 需要去找操作系统申请
后期:
synchronized(Object)
markdown 记录这个线程的 ID 偏向锁 只记录ID,不锁(默认没有第二个线程来访问)
如果有线程争用:升级为 自旋锁 循环10次(占用CPU)
10次之后,升级为重量级锁 去操作系统申请锁(不占用 CPU)
自旋锁:在用户态解决问题,不经过内核态。
执行时间长的用系统锁,(加锁代码)执行时间特别短,线程较少,用自旋锁。