首先我们要明确线程的概念:
在系统中一个并行者多个进程,进程的启动由cpu负责分配时间片,当进程获取到时间片后开始运行,时间片结束后停止运行。线程就类似于进程,当进程获取到时间片后将时间片进行重新划分并分配给进程中的线程,当线程获取时间片后开始运行,时间片结束停止运行,所以线程也可以称为轻量级进程。
基于java的编程思想:一切皆为对象的方式来说,线程也是一种对象
线程安全:线程的运行过程中所执行的方法都带有锁标记
线程:在一个进程中,并发的一个顺序执行的流程
进程:OS中并发的一个任务(进程中堆空间和栈空间都是独立的)
并发:多个程序同时运行;
CPU的运行过程:分时间片运行 宏观并行 微观串行;
1.如何创建一个线程
(1)实现Runnable接口实现run方法
实现接口最大的好处就是解耦合,不会影响本类原有的继承关系。
(2)继承Thread类覆盖run方法
Thread类本身也是一个实现了Runnunnable接口的一个实例,它代表一个线程的实例。
并且,继承Thread类唯一的启动线程方法就是start()方法,start()方法是一个native方法,它将启动一个新线程,执行run()方法;
(3) 实现Callable接口
①优点:可抛异常,可有返回值;
②获取Callable的返回值:
先提交线程获取Future对象然后调用Future的get()方法获取线程返回值;
2.线程运行状态图
3.锁
为了确保线程安全我们通常使用synchronized为方法/对象加锁,使得并发处理时一个方法/对象在同一时间只被一个线程对象访问,锁的种类有很多,同时原理也各不相同。
锁是java并发编程中最重要的同步机制,锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息,保证线程安全。
简单介绍几种锁:
①无锁算法:使用CAS算法基于链表实现,主要包含原子量、并发集合、同步器、可重入锁,并对线程池的构造提供了强力的支持。
②自旋锁:自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,它会阻塞其它线程,当前线程没有获取到锁标记时会不断持续的尝试获取锁,不会睡眠。
③自旋锁的其他种类
④阻塞锁:加锁后,线程得不到锁标记将被阻塞,放入阻塞队列中。
⑤可重入锁:一个线程中可以多次获取同一把锁。
⑥读写锁:所有写操作不会互斥。
⑦互斥锁:如果资源已经被占用,资源申请者只能进入睡眠状态。
⑧悲观锁:会认为所有操作都会改变资源,所以会在所有操作前加锁。
⑨乐观锁:认为操作不会改变资源,在更新时判断是否有操作,可以提高运行效率。
⑩公平锁:加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得。
⑪非公平锁:加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待。
⑫对象锁:保证同一时间此对象只被一个线程访问。
⑬线程锁:保证同一时间纸杯一个线程调用此方法。
⑭轻量级锁:只减少多线程进入互斥的几率,尝试在进入互斥前进行补救。
4.对于线程池不想写太多了,写下我自己对线程池概念的理解然后 点这里
线程池主要用于减少线程的创建和销毁时间、解决多线程占用资源过多和提高服务器响应时间。
首先我们先创建一个线程池,然后为线程池中准备一些可使用线程,当有请求到达时,将调用线程池中的一个线程来执行相应的任务,当线程池中没有闲置的线程时,当前请求将进入线程池的缓冲区进入等待。
对于线程池我们可以比喻成一个房子,线程中的线程比喻成可以干活的工人,当有雇主发布任务时就会叫一个工人为自己工作,工人工作完毕后会回到房子中,等新的雇主来发布任务;当有新的雇主过来却发现房子里面没有工人时,他就会在房子附近等工人回来。