一、博客状态
多线程的5种状态我也记下了,写出来也没意思。直接引用前辈的博客吧
http://www.cnblogs.com/skywang12345/p/3479024.html
主要5种:新建、就绪、运行、阻塞、死亡。
二、实现多线程的三种方式:
https://www.jianshu.com/p/9e489390fc46
主要区别:
Runnable接口相比继承Thread类
- 可以避免由于Java的单继承特性而带来的局限
- 增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的
- 适合多个相同程序代码的线程去处理同一资源的情况
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类
实现Runnable接口和实现Callable接口的区别
- Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
- 实现Callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程不能返回结果
- Callable接口的call()方法允许抛出异常,而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛
- 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用submit方法
三、多线程API
start()和run()的区别
start()会启动一个新线程,并在新线程中运行run()方法。
run()则会直接在当前线程中运行run()方法,并不会启动一个新线程来运行run()。相当于一个普通的方法调用而已。
线程等待与唤醒
http://www.cnblogs.com/skywang12345/p/3479224.html
线程休眠
http://www.cnblogs.com/skywang12345/p/3479256.html
等待和休眠的区别:
wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。
线程让步
http://www.cnblogs.com/skywang12345/p/3479243.html
interrupt()和线程终止方式
http://www.cnblogs.com/skywang12345/p/3479949.html
线程优先级和守护线程
http://www.cnblogs.com/skywang12345/p/3479982.html
join方法
让“主线程”等待“子线程”结束之后才能继续运行
这个我们可以看看join的源码
public final void join() throws InterruptedException {
join(0);
}
public 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) { //如果时执行的join(0)
while (isAlive()) { //如果线程是运行状态,就会执行下面的等待
wait(0);
}
} else { //如果是执行的join(time)
while (isAlive()) { //如果线程时运行状态
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay); //等待delay时间后自动返回继续执行
now = System.currentTimeMillis() - base;
}
}
}
其实join方法本质就是利用上面的线程实例作为对象锁的原理,当线程终止时,会调用线程自身的notifyAll()方法,通知所有等待在该线程对象上的线程的特征。
主线程并没有别的线程使用notify或notifyAll方法唤醒,竟然直接执行了后面的语句"执行了这里"。原来如果synchronized获得对象锁是线程的实例时,此时比较特殊,当该线程终止的时候,会调用线程自身的notifyAll()方法,会通知所有等待在该线程对象上的线程。
参考博客
https://blog.csdn.net/chenkaibsw/article/details/80912878