Java多线程笔记

2019-10-23  本文已影响0人  阿豪puls

1、多线程基本概念

2、并行与并发的区别

3、创建线程的方式

3.1 方式一:继承Thread类

1、继承Thread类,重写父类的run()方法
2、调用线程对象的start()方法,而不是run()方法

3.2 方式二:实现Runnable接口

1、实现Runnable接口,重写接口的run()方法
2、通过Thread类的构造器创建多线程
3、将Runnable的实现类作为参数传递给Thread类的构造器,创建Thread类的对象
4、调用Thread类的start()方法开启线程

3.3 方式三:实现Callable接口

1、实现Callable接口,重写call()方法
2、将Callable接口的实现类作为参数,传递给FutureTask类的构造器,创建FutureTask类的对象
3、将FutureTask类作为参数传递给Thread类的构造器,创建Thread类的对象
4、调用Thread类的start()方法开启线程
5、较Runnable相比,具有返回值、可抛出异常
6、获取返回值,需借助FutureTask类的get()方法,在开启start()方法之后调用

3.4 方式四:创建线程池

背景:经常创建和销毁,使用量特别大的资源,比如并发编程对性能影响很大
解决思路:提前创建好多个线程,放入线程池,使用时直接获取,使用放回池中,避免了频繁创建和销毁线程的开销


image.png

注意事项:
1、如果调用的run()方法,那就跟调用普通方法一样,无法启动多线程
2、一个线程只能调用一次start()方法,多次调用将抛出异常 "IIIeglThreadStateException"

4、继承方式和实现方式的区别

5、多线程引发出来的连锁思考

6、Thread常用方法

1、start():启动当前线程;调用当前线程的run()
2、run(): 通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
3、currentThread():静态方法,返回执行当前代码的线程
4、getName():获取当前线程的名字
5、setName():设置当前线程的名字
6、yield():释放当前cpu的执行权
7、join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。
8、stop():已过时。当执行此方法时,强制结束当前线程。
9、sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前线程是阻塞状态。
10、isAlive():判断当前线程是否存活

7、 线程优先级

高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下
被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。

7、线程的生命周期

1、新建:当一个Thread类或其子类的对象被实例化,新生的线程处理新建状态
2、就绪:当新建的线程被start()后,线程处理就绪,等待着cpu时间片,具备运行条件
3、运行:当就绪的线程分配到cpu资源时,便进入了运行状态,调用run()方法,执行业务逻辑
4、阻塞:当被人为挂起或执行输入输出操作时,让出cpu时间片并临时终止自己的执行,进入阻塞状态
5、死亡:线程完成工作后、线程被强制退出、出现异常,都会导致线程结束,进入死亡状态

线程的生命周期

8、线程同步

8.1、出现的问题

当多个线程同时操作同一份共享数据时,一个线程执行了一部分,另一个线程参与进来,会造成共享数据的不完整性

8.2、如何解决线程共享带来的问题

给共享数据加锁(Synchronized),一次只能被一个线程访问,当线程操作完共享数据时,释放锁

8.3、线程同步机制

1、必须确保使用同一资源的多个线程共用一把锁,否则无法保证线程安全
2、 如果使用Runnable方式实现的多线程,用this关键字,可充当同步监视器
3、如果使用Thread继承方式实现的多线程,请用当前类.class或者静态对象,充当同步监视器,如果使用this关键字的话,即每个线程实例对象同时拥有自己的共享数据

8.3.1、同步代码块
synchronized (this){
}
8.3.2、同步方法
private synchronized void show(){//同步监视器:this
}
private static synchronized void show(){//同步监视器:即为当前类.calss
}
8.3.3、Lock(锁)
使用方法
8.3.4、synchronized与Lock的区别

synchronized:
1、隐式锁出了作用域自动释放
2、具有同步代码块锁和方法锁,2种锁方式
Lock:
1、显示锁(需手动开启和关闭锁)
2、只有代码块锁,没有方法锁
3、JVM将花费更少时间调度线程,性能会更好些

9、线程的死锁

9.1、死锁原因

1、不同的线程分别占用对方需要的同步资源不放弃,都在等待对方释放自己需要的同步资源,就形成了死锁
2、出现死锁后,并不会抛出异常和提示信息,所有线程处于阻塞状态,无法继续执行操作

9.2、解决方案

1、尽量减少同步资源的定义
2、尽量避免使用嵌套同步

10、线程的通信

线程与线程之间难免会相互协作去完成一件较复杂的功能,典型的例子生产者-消费者

1、wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中
2、wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现IllegalMonitorStateException异常
3、wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中

上一篇 下一篇

猜你喜欢

热点阅读