1.创建、启动线程的方式
public class CreateMyThread {
static class MyThread extends Thread{
@Override
public void run() {
System.out.println("Hello Mythread!");
}
}
static class MyRun implements Runnable{
@Override
public void run() {
System.out.println("Hello MyRun!");
}
}
public static void main(String[] args) {
//继承Thread类
new MyThread().start();
//实现Runnable接口
new Thread(new MyRun()).start();
//lambda表达式
new Thread(()->{
System.out.println("Hello lambda!");
}).start();
}
}
方法:
sleep:线程休眠
yield:线程进入等待队列,CUP可能重新调起当前线程或者其他等待线程
join:让其他线程加入当前线程,等待其他线程执行结束在开始执行
线程状态迁移图:
synchronized
synchronized锁的是对象,不是代码
锁方法锁的是this,锁static方法锁的是class
锁定方法和非锁定方法是可以同时执行的)(可重入)
锁升级从偏向锁到自旋锁再到重量级锁
- 锁的形式:
- synchronized(object); 锁定对象,不能用String常量(可能大家都在用,有其他lib类库也用这个常量,用户线程的人也去用这个常量,会乱)、Integer、Long
- synchronized(this); 锁定当前对象
- synchronized(T。class); 锁定当前对象
2.锁定方法与非锁定方法同时执行
public class Sync1 {
/**
* 锁定方法与非锁定方法同时执行
*/
public static synchronized void m1(){
System.out.println("m1 start ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("m1 end ...");
}
public static void m2(){
System.out.println("m2 start ...");
}
public static void main(String[] args) {
new Thread(Sync1::m1).start();
new Thread(Sync1::m2).start();
}
}
输出:
m1 start ...
m2 start ...
m1 end ...
3.可重入锁
public class Sync2 {
/**
* 可重入锁
*/
static synchronized void m1(){
System.out.println("m1 start ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
m2();
System.out.println("m1 end ...");
}
static synchronized void m2(){
System.out.println("m2 start ...");
}
public static void main(String[] args) {
new Thread(Sync2::m1).start();
}
}
输出:
m1 start ...
m2 start ...
m1 end ...
4.乱入锁(锁中间产生异常)
public class Sync3 {
/**
* 异常 乱如锁
*/
private int i = 0;
synchronized void m1(){
System.out.println(Thread.currentThread().getName()+" : start ...");
while (true){
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 5){
i = 1/0;// 异常
}
System.out.println(Thread.currentThread().getName()+" : "+ i);
}
}
public static void main(String[] args) {
Sync3 s = new Sync3();
Runnable r = new Runnable() {
@Override
public void run() {
s.m1();
}
};
new Thread(r,"t1").start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(r,"t2").start();
}
}
输出:
t1 : start ...
t1 : 1
t1 : 2
t1 : 3
t1 : 4
t2 : start ...
Exception in thread "t1" java.lang.ArithmeticException: / by zero
at com.frngzi.threadTest.Demo1.Sync3.m1(Sync3.java:18)
at com.frngzi.threadTest.Demo1.Sync3$1.run(Sync3.java:29)
at java.lang.Thread.run(Thread.java:748)
t2 : 6
t2 : 7
5.synchronized 锁升级
偏向锁:sync(Object),对象头上面的markword记录这个线程ID
自旋锁:偏向锁有线程争用,升级为自旋锁
重量级锁:自旋锁转圈10次之后,升级为重量级锁,就是取操作系统那里去申请资源
锁只可以升级,不可以降级;
1.执行时间短(加锁代码),线程数少 - 自旋锁
2.执行时间长,线程数多 - 系统锁
6.synchronized 锁优化
- synchronized锁的细化,加只需要加锁的代码
- synchronized锁的粗化
- synchronized锁对象的时候,对象变成了另外一个对象,那么锁失效,一般会在锁对象前加final修饰,不可变。