多线程基础概念
进程: 资源分配最小单位
线程: cpu执行程序的最小单位
一个进程在这里插入代码片程必须有一个线程,一个线程可以包含多个线程
什么是线程:进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。
那什么是多线程:提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程。
所谓串行,其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子:当我们下载多个文件时,在串行中它是按照一定的顺序去进行下载的,也就是说,必须等下载完A之后才能开始下载B,它们在时间上是不可能发生重叠的。
并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻发生的,并行在时间上是重叠的。
如何确保线程安全:
synchronized
synchronized关键字,就是用来控制线程同步的,保证我们的线程在多线程环境下,不被多个线程同时执行,确保我们数据的完整性,使用方法一般是加在方法上。
public class ThreadDemo {
int count = 0; // 记录方法的命中次数
public synchronized void threadMethod(int j) {
count++ ;
int i = 1;
j = j + i;
}
}
这样就可以确保我们的线程同步了,同时这里需要注意一个大家平时忽略的问题,首先synchronized锁的是括号里的
对象,而不是代码,其次,对于非静态的synchronized方法,锁的是对象本身也就是this。
当synchronized锁住一个对象之后,别的线程如果想要获取锁对象,那么就必须等这个线程执行完释放锁对象之后才
可以,否则一直处于等待状态。
注意点:虽然加synchronized关键字,可以让我们的线程变得安全,但是我们在用的时候,也要注意缩小
synchronized的使用范围,如果随意使用时很影响程序的性能,别的对象想拿到锁,结果你没用锁还一直把锁占用,
这样就有点浪费资源。
lock
先来说说它跟synchronized有什么区别吧,Lock是在Java1.6被引入进来的,Lock的引入让锁有了可操作性,什么意思?就是我们在需要的时候去手动的获取锁和释放锁,甚至我们还可以中断获取以及超时获取的同步特性,但是从使用上说Lock明显没有synchronized使用起来方便快捷。我们先来看下一般是如何使用的:
private Lock lock = new ReentrantLock(); // ReentrantLock是Lock的子类
private void method(Thread thread){
lock.lock(); // 获取锁对象
try {
System.out.println("线程名:"+thread.getName() + "获得了锁");
// Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
} finally {
System.out.println("线程名:"+thread.getName() + "释放了锁");
lock.unlock(); // 释放锁对象
}
}
进入方法我们首先要获取到锁,然后去执行我们业务代码,这里跟synchronized不同的是,Lock获取的所对象需要我们亲自去进行释放,为了防止我们代码出现异常,所以我们的释放锁操作放在finally中,因为finally中的代码无论如何都是会执行的。
总结:
1:进程和线程上锁都会从异步变成同步,有先有后,如果必须要同步执行操作(有先有后),将执行操作的内容前后进行上锁(上锁和解锁是一对)
2:一个进程必须有一个线程,一个线程可以包含多个线程
3:使用进程和线程(可以不引)的时候,要引入 if __name __ ==’__main __’:
4;在定义锁后,函数在使用锁时,会把锁返回的对象当做参数传进去
5:并发多线程和多进程 , 多线程的速度更快!
6:线程锁一般加在外面,进程锁一般是修改哪里加在哪里
7:当创建进程或者线程的时候是异步的.当执行某个方法时候,各个进程或者线程之间是同步的
8:在定义事件后,函数在使用事件时,会把事件返回的对象当做参数传进去
9:进程相当于一块地,线程是地里面干活的工人(工人可以是多个)
10:如果wait中有参数.代表是最多阻塞几秒,等待几秒后就开始执行,如果不加参数,会一直阻塞(除非将False改为True)
11:在使用Queue时,为了等待子进程把数据塞到队列中,在获取,要加一个join
12:在定义进程Queue和JoinableQueue后,函数在使用Queue和JoinableQueue时,会把Queue和JoinableQueue返回的对象当做参数传进去
13;在定义Manager后,然后在创建一个共享字典或者列表,函数在使用Manager时,会把创建共享字典或者共享列表返回的数据当做参数传进去
14:在使用Manage时候,必须要使用锁和join.
15:在进程的queue 或者jionablequeue共享数据是一个进程将数据传到另外一个进程中,是属于获取或者是储存,manager共享数据是进程修改共享的数据
16:在定义线程Queue和LifoQueue,PriorityQueue后,函数在使用Queue和Queue和LifoQueue,PriorityQueue时,会把Queue和Queue和LifoQueue,PriorityQueue返回的对象当做参数传进去
17:每一个进程必须有一个主线程,一个主线程可以包含多个子线程
18:并发(一个CPU执行多个)多线程和多进程 , 多线程速度更快(线程不需要开辟空间,进行要开辟空间)
19:线程和进程都是异步并发的程序(一个CPU执行多个),有阻塞会跳过,一个进程里面的线程也会创建多个子线程.
20:创建的多线程或者多进程返回的都是对象