1.进程和线程概念
进程:是程序的一次执行过程,是系统运行程序的基本单位,占有独立的内存空间
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行
特点:一个应用程序可以有多个进程,一个进程可以有多个线程
2.线程调度:
分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度
3.thread类
构造方法
| Thread() : | 分配一个新的线程对象。 |
|---|---|
| Thread(String name) : | 分配一个指定名字的新的线程对象。 |
| Thread(Runnable target) : | 分配一个带有指定目标新的线程对象。 |
| Thread(Runnable target,String name) : | 分配一个带有指定目标新的线程对象并指定名字。 |
常用方法
| String getName() | 获取当前线程名称。 |
|---|---|
| void start() | 导致此线程开始执行; Java虚拟机调用此线程的run方法。 |
| void run() | 此线程要执行的任务在此处定义代码。 |
| static void sleep(long millis) | 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。 |
| static Thread currentThread() | 返回对当前正在执行的线程对象的引用。 |
注意:sleep方法本身带有异常,需要处理异常
4.创建线程类(方式一):
a. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。
b. 创建Thread子类的实例,即创建了线程对象
c. 调用线程对象的start()方法来启动该线程
例子:
public class MyThread extends Thread {@Overridepublic void run() {//代码}}
start()方法会开辟一块新的栈空间,并在里面调用run()方法。
5.创建线程(方法二):
a. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
b. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正 的线程对象。
c. 调用线程对象的start()方法来启动线程。
例子:
public class MyRunnable implements Runnable{@Overridepublic void run() {}}public class Demo {public static void main(String[] args) {MyRunnable mr = new MyRunnable();Thread t = new Thread(mr);t.start();}}
区别:
1.避免了单继承的局限性:实现Runnable接口之后还可以继承或者实现其他类和接口
2.增强了程序的拓展性,降低程序的耦合性:实现Runnable接口的方式,把设置线程和开启线程的任务进行了分离(解耦)
6 .匿名内部类:简化代码,将子类继承父类,重写父类的方法,创建子类对象合成一步(或者接口也一样)
格式:
new 父类/接口( ){
重写父类/接口中的方法
}.start();
例子:
Runnable r = new Runnable(){public void run(){}}new Thread(r).Start();//或者直接将new Rannable构造匿名类放入Thread构造参数中,一步到位
7.线程同步
同步代码块:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
格式:
synchronized(同步锁对象){
需要同步操作的代码
}
注意:
a.锁对象可以是任意类型
b.多个线程对象要使用同一把锁
同步方法:
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
注意:同步方法中使用调用这个方法的类作为锁对象,也就是this。如果是静态同步方法,锁对象是RunnableImpl.class类
Lock锁:
方法:
public void lock() 加同步锁
public void unlock() 释放同步锁。
格式:lock锁通过子类ReentrantLock创建对象来使用
Lock lock=new ReentrantLock();
使用:在关键代码之前上锁,在关键代码之后解锁
注意:可以将解锁放到finally中,这样无论如何都会释放锁
8.线程状态
9.线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
格式:
ExecutorService 线程池名 = Executors.newFixedThreadPool(线程数量)
步骤:
1. 创建线程池对象
2. 创建Runnable接口子类对象
3. 通过线程池对象的.submit(接口子对象)方法实现线程的取用和运行
4. 关闭线程池(一般不做)
9.Lambda表达式:做什么,而不是怎么做
格式:(参数类型 参数名称) -> { 代码语句 }
说明:仅仅保留最关键的参数和方法体
省略规则:
a. 小括号内参数的类型可以省略;
b. 如果小括号内有且仅有一个参,则小括号可以省略;
c. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
使用前提:
a. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的Runnable、Comparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
b. 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
