目录
相关文章:
一、多线程创建
1、thread/runnable
2、两种启动线程方法的区别
3、start方法和run方法的区别
二、线程间通信
1、synchronized关键字
a、synchronized对象锁
b、synchronized来实现线程间通信
c、synchronized/volatile
d、synchronized/lock
2、sleep/wait
3、wait/notify机制
三、线程池
1、好处
2、框架ThreadPoolExecutor
3、线程池的工作流程
相关文章:
一、多线程创建
1、thread/runnable
继承Thread类,实现Runnable接口
2、两种启动线程方法的区别
共同点:
不同点:
一般来讲更倾向于实现Runnable接口,因为这种方式比继承Thread类有更多优势:
- 避免Java单继承带来的局限性,
- 增强程序的健壮性,代码能够被多个线程共享,同时数据又是各自独立的
- 适合多个相同程序的代码在处理同一资源的时候能够复用
3、start方法和run方法的区别
二、线程间通信
1、synchronized关键字
a、synchronized对象锁
b、synchronized来实现线程间通信
通过不同的线程去共享同一个变量来进行锁的管理。
c、synchronized/volatile
被volatile修饰的变量不允许线程从主内存中将变量值拷贝到自己的存储空间。所以,这个变量将在所有线程中保证数据同步。例如,线程A和线程B都在操作这个值,如果线程A中该变量的发生变化,那么线程B也会得到通知而相应的同步这个变量。
两者的区别:
- 1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
- 2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
- 3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
- 4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
- 5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。
相关文章:java多线程synchronized volatile解析
d、synchronized/lock
synchronized
是隐式锁,在需要同步的对象中加入此控制,而lock
是显示锁,需要显示指定起始位置和终止位置。
- 使用lock时在finally中必须释放锁,不然容易造成线程死锁;而使用synchronized时,获取锁的线程会在执行完同步代码后释放锁(或者JVM会在线程执行发生异常时释放锁)。
- 使用lock时线程不会一直等待(CPU乐观锁机制);而使用synchronized时,假设A线程获得锁后阻塞,其他线程会一直等待(CPU悲观锁机制)。
- 性能上:synchronized是托管给JVM来执行的,而lock是我们java代码自己写的控制锁,所以synchronized在性能上要更低效,因为它是一个重量级的操作。
2、sleep/wait
sleep()睡眠时,保持对象锁,仍然占有该锁;其他线程无法访问
而wait()睡眠时,释放对象锁。其他线程可以访问
3、wait/notify机制
相关文章:Wait/Notify通知机制解析
【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明
三、线程池
1、好处
- a、降低资源消耗:通过重复利用已经创建好的线程来降低线程创建或者销毁所带来的消耗
- b、提高响应速度:有了线程池,任务可以很快就得到执行而不用等待线程创建
- c、提高线程的可管理性:线程毕竟是比较稀缺的资源,尤其对于手机而言,我们不可能不限制的创建线程,使用线程池可以对系统资源进行统一的分配
2、框架ThreadPoolExecutor
public ThreadPoolExecutor(
//线程池的基本大小
int corePoolSize,
//线程池最大容量
int maximumPoolSize,
//线程存活时间
long keepAliveTime,
//时间单位
TimeUnit unit,
//阻塞队列
BlockingQueue<Runnable> workQueue,
//创建线程的工厂
ThreadFactory threadFactory,
//这个handler是线程池的保护策略,当线程池满的时候,及时告诉调用
//者,以采取应对措施,从而提高程序健壮性
RejectedExecutionHandler handler) {...}
3、线程池的工作流程
a、首先线程池判断基本线程池是否已满
b、其次线程池判断工作队列是否已满
c、最后线程池判断整个线程池是否已满