多线程
1、线程,程序,进程的基本概念,及其它们之间的关系
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的
线程是一个比进程更小的执行单位,一次进程可以产生多个线程,与进程不同的是同一个进程的线程共享进程的堆和方法区资源,而每个线程都用拥有各自的程序计数器,虚拟机栈和本地方法栈,所以系统产生一个线程时,负担要比进程小的多,就是因为如此,线程被称为轻量级的进程
2、为什么要使用多线程呢?
现在的系统动不动要求处理百万级千万级的数据量,使用多线程正是开发高并发系统的基础,利用好多线程技术可以大大提高系统高并发能力及性能
现在是多核CPU时代,多线程可以提高cpu利用率
3、使用多线程可能遇到的问题?
并发编程的目的就是提高程序的执行效率提高程序运行效率,但并发编程还是会导致一些问题:比如内存泄漏、
上下文切换,死锁,还有受限于硬件和软件的资源闲置问题
4、 线程的生命周期和状态
初始状态
运行状态
阻塞状态
等待状态
超时阻塞状态
5、线程死锁
多个线程同时处于被阻塞状态,而它们中的一个或者全部都在等待资源被释放,由于线程无期限的阻塞,因此程序不可能结束
实例
package com.hya.helloworld;
public class DeadLockDemo {
private static Object resource1 = new Object();
private static Object resource2 = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"wait get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
,"线程1" ).start();
new Thread(()->{
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"wait get resource1");
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
}
}
}
,"线程2" ).start();
}
}
死锁产生的四个条件:
互斥条件:该资源任意时刻只由一个线程掌握
请求与保持条件:一个进程请求资源而阻塞时,对已拥有的资源保持不放
不剥夺条件:线程已获得资源在未使用之前不能强行剥夺,只能等自己使用 完毕才能释放
循环等待条件:线程之间形成一种头尾相接的循环等待资源关系
如何避免死锁?
破坏循环等待条件,按排序申请资源,反序释放资源
package com.hya.helloworld;
public class DeadLockDemo {
private static Object resource1 = new Object();
private static Object resource2 = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"wait get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
,"线程1" ).start();
new Thread(()->{
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"wait get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
,"线程2" ).start();
}
}
6、为什么我们调用start方法是会执行run方法,为什么我们不能直接调用run方法?
因为在新建一个线程时,调用start方法会让此线程启动处于就绪状态,当分配到时间片时就能开始运行了,start方法为线程提供准备工作,线程会执行run方法。而直接调用run方法时,run方法只是线程中的一个普通方法而已,还是在主线程中执行
7、synchronized关键字(同步)
synchronized解决的是多个线程之间访问资源的同步问题,synchronized可以保证它所修饰的方法或代码块在任意时刻只能有一个线程执行
浙公网安备 33010602011771号