1、进程与线程的概念
进程:一个独立应用程序 线程:其实就是一个执行路径
进程是所有线程的集合,每一个线程是进程中的一条执行路径
2、多线程应用场景:迅雷多线程下载、数据库连接池、分批发送短信...
多线程不能提高下载速度,只能提高程序效率
3、多线程的好处:多线程提高程序效率
4、同步与异步
同步:代码从上至下,顺序执行
如果方法1出现异常,方法2也会受到影响
异步:开辟一条新的执行路径,不会影响其他线程
方法1、方法2互不影响
5、多线程创建的方式
- 继承Thread类 重写run方法
- 实现Runnable接口 重写run方法
- 使用匿名内部类的方式
实现Runnable接口的好处:实现了接口还可以继续继承,继承了类不能再继承(Java只能单继承)
6、多线程的运行状态
新建状态:创建一个线程,例如new Tread()
就绪状态:启动线程 调用start()方法,阻塞状态的线程唤醒后会进入就绪状态,继续争夺CPU使用权
运行状态:获得CPU的使用权,开始执行run方法
死亡状态:(1)run方法正常退出而自然死亡(2)一个未捕获的异常终止了run方法而使线程猝死
阻塞状态:
- 线程通过调用sleep方法进入睡眠状态;
- 线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
- 线程试图得到一个锁,而该锁正被其他线程持有;
- 线程在等待某个触发条件;
7、 Java中有两种线程,一种是用户线程,另一种是守护线程。
用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止(非守护线程)
守护线程当进程不存在或主线程停止,守护线程也会被停止。(例如,GC线程)
使用setDaemon(true)方法设置为守护线程
8、join()方法 :获取使用权
当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1
示例代码:join()的使用 放在start()的后面 线程先开启,再设置是否将CPU使用权让给它
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
});
thread.start();
thread.join();//主线程会将CPU使用权让给thread
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
控制台显示结果:先打印Thread-0的信息,打印完Thread-0的所有信息后;再打印main的信息
示例代码:守护线程 setDaemon方法放在start()之前 线程先设置为守护线程,再将其开启
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
});
thread.setDaemon(true);//将其设置为守护线程
thread.start();
for (int i = 0; i <30; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}