慕课学习链接
Thread join 方法 用途某一线程执行完毕,才能执行后续的方法。
异常join 方法会 throws InterruptedException,所以使用时,要么捕获,要么抛出。
使用创建3个线程,等3个线程都执行完成再进行响应操作。
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"sleep 1s");
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"sleep 5s");
}
});
Thread t3 = new Thread(new Runnable(){
@Override
public void run(){
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"sleep 8s");
}
});
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("end");
}
不使用 join 方法,先输出 “end” ,再输出 线程1,2,3的执行。
使用 join 之后,线程执行完成之后才会输出 “end”。有点像异步时设置参数为同步。
有参数的 join 方法join(毫秒数) n毫秒之后不再等待。Thread yield 方法 用途
谦让,在没有用完 CPU 分配的时间时,主动让出 CPU 时间,给其他同优先级的线程使用。
特点static 静态的,Thread.yield() 直接调用。
native 本地,调用非 Java 语言实现的方法,操作操作系统。
使用创建一个线程,执行1-10000 的累加,加入 yield 方法,执行速度较慢。
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
int sum = 0;
for(int i=0;i<10000000;i++){
sum = sum + i;
Thread.yield();
}
}
});
long cur = System.currentTimeMillis();
t1.start();
t1.join();
System.out.println(System.currentTimeMillis()-cur);
}
sleep() yield() 区别
sleep() 方法,线程阻塞,允许其他所有线程先执行,会抛出异常,可移植性好。
yield() 方法,线程就绪,只允许优先级相同或更高的线程先执行,不会抛异常。
上下文切换和死锁 上下文切换一个线程 CPU 分配的时间片用完,或者被中断,进入就绪状态,需要保存执行到的状态,让出 CPU 给其他线程执行,这就是上下文切换。
线程死锁:两个或两个以上的线程,因争夺资源互相等待,没有外力的作用下,会一直等待下去。
死锁的必要条件互斥:一个资源一段时间只能被同一个进程占用
不可剥夺:不能被强制终止。
请求与保持:占有一个资源,请求另一个资源
循环等待
死锁实现 public static void main(String[] args) throws InterruptedException {
Object a = 1;
Object b = 2;
Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
synchronized (a){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1 -> b" );
synchronized (b){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("end" );
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run(){
synchronized (b){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("2 -> a" );
synchronized (a){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("end" );
}
});
t1.start();
t2.start();
}
破坏必要条件,避免死锁
只有请求保持和循环等待可以破坏,以上,通过调整获取资源的顺序,都是 先获取a,再获取b,避免循环等待,可以避免死锁。



