第 24 节课 多线程

目录

同步的好处:

同步的弊端:

死锁问题:

如何添加等待唤醒机制呢?

如何实现线程池的代码呢?

总结

多线程:

线程池:


同步的好处:

解决了多线程的安全问题

同步的弊端:

加入了同步之后,就相当于加了一把锁,这样每次进入同步代码块之前都会判断一下,无形之中,降低了程序的运行效率

1、同步代码块的锁对象是谁?

任意对象

2、同步方法的时候,锁对象又是谁呢?

this

3、如果是静态同步方法,锁对象是该静态同步方法所属那个类的字节码文件,字节码文件也属于一种对象。

我们之前解决线程同步安全的时候,是使用synchronized关键字,通过我们的分析得出将哪些代码块给包起来,但是,我们并没有直接看到哪里上了锁,在哪里释放了锁让其他线程拿到。为了更清晰的表达如何加锁以及释放锁,在JDK1.5之后提供了一个新的锁对象Lock

Lock:(接口)

具体的子类:ReentrantLock

void lock() 获得锁

void unlock() 释放锁

哪些是线程安全的类:

Vector虽然是线程安全的,我们今后开发也不用它,

工具类,用该工具类下面方法得到的所有集合都是可以线程安全的:

Collections

死锁问题:

两个或者两个以上的线程在争夺资源的过程中,出现了相互等待的现象,叫死锁现象。

同步的弊端:

1、效率低

2、容易产生死锁

线程间的通信

针对同一个资源的操作有不同种类的线程

可能出现的问题和原因:

1、同一个数据连续出现了很多次

CPU一点点的时间片就足以线程执行很多次

2、姓名和年龄与我们给的不匹配

这是由线程运行具有随机性导致的

3、存在线程安全问题:

1)是否存在多线程环境 是

2)是否存在共享数据 是

3)是否有多条语句操作着共享数据 是

都满足,说明存在线程安全问题

解决方案:

加锁

注意:

1、不同种类的线程类中都需要加锁

2、不同种类的线程类中的锁对象必须要是同一个

我们虽然解决了线程安全问题,但是程序中存在等待唤醒机制的问题。加入等待唤醒机制。

如何添加等待唤醒机制呢?

Object类中存在三个方法:

void wait() 导致当前线程等待,直到另一个线程调用该对象 notify()方法或 notifyAll()方法

void notify() 唤醒正在等待对象监视器的单个线程

void notifyAll() 唤醒正在等待对象监视器的所有线程

为什么这些方法不定义在Thread类中?

这些方法想要调用,必须通过锁对象进行调用,而我们知道锁对象可以是任意锁对象,所以这些方法,就必须定义在Object类中。

线程组:把多个线程组合到一起

JAVA中使用ThreadGroup来表示线程组

它可以对一批线程进行分类管理

JAVA允许程序直接对线程组进行控制的

线程池中的每一个线程代码结束后,并不会死亡

而是再次回到线程池中成为空闲状态,等待下一个对象来使用

如何实现线程池的代码呢?

1、创建线程池对象,Executors工厂类下的静态方法,newFixedThreadPool是其中一种线程池

public static ExecutorService newFixedThreadPool(int nThreads)

2、往线程池中放线程:(可以放哪些线程?)

3、在线程池中的线程怎么运行呢?

4、我想结束线程的运行,可不可以手动结束?如果可以怎么结束

shutdown()结束线程。

多线程的实现方式三:实现Callable接口,重写call方法,结合线程池运行

Future submit(Callable task)

提交值返回任务以执行,并返回代表任务待处理结果的Future

常见的情况:

1、新建--就绪--运行--死亡

2、新建--就绪--运行--就绪--运行--死亡

3、新建--就绪--运行--等待阻塞--同步阻塞--就绪--运行--死亡

4、新建--就绪--运行--同步阻塞--就绪--运行--死亡

5、新建--就绪--运行--其他阻塞--就绪--运行--死亡

============================================

总结

多线程:

指的一个程序中有多条执行路径的情况,我们称之为多线程程序

多线程的实现方式:

1、继承Thread类,重写run()方法,调用start()方法启动

2、实现Runnable接口,重写run()方法,创建Thread对象把Runnable对象当作参数传递,

调用start()方法启动

3、实现Callable接口,重写call()方法,提交到线程池中运行,需要结合线程池

newFixedThreadPool

newCachedThreadPool

newSingleThreadExecutor()

newScheduledThreadPool

线程的同步安全问题:

造成线程同步问题的原因:(三个条件同时存在)

1、是否存在多线程环境

2、是否存在共享数据/共享变量

3、是否有多条语句操作共享数据/共享变量

解决线程的同步安全问题方案

方案一:

同步代码块:

格式:synchronized(锁对象){

需要同步的代码(操作共享数据/共享变量的代码块)

}

锁对象的使用:

注意:发生同步安全的多线程之间的锁对象要一致,锁对象唯一

正常情况下:锁对象是任意对象

同步方法:锁对象是this

同步静态方法:锁对象是当前类的字节码文件对象

方案二:

Lock锁,JDK1.5之后出现

lock() 加锁

unlock() 释放锁

生产者消费者问题:

解决方案:

等待唤醒机制:(前提是线程没有同步安全问题)

Object类下提供了三个方法:

wait()

notify()

notifyAll()

线程组:将多个线程分组,放到一组,程序可以直接操作线程组(比如设置守护线程)

线程池:

好处:

线程池里的每一个线程代码结束后,并不会死亡,

而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

匿名内部类的形式创建线程对象并启动

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值