实现多线程的方式
- 实现Runnable(无返回值)
- 实现Callable(Future接收返回值)
- 继承Thread
- 线程池Executors创建工作线程来执行任务线程
线程的几种状态
线程状态变化.png多线程同步的几种方法
- synchronized
- Lock
- 分布式锁(Redis,Zookeeper等实现)
死锁
两个线程互相等待对方释放对象锁
start()和run()的区别
start():启动线程,使线程从new状态变成runnable状态,等待os选中
run():普通的方法调用,是同步执行的
多线程之间通信
- 共享变量【隐式】
- 消息传递(wait/notify)【显式】
线程池和一般手动创建线程相比的好处
- 一般手动创建线程每次都要new Thread(new XxxRunnable()).start()创建对象实例并启动线程
- 每个线程都会占用内存资源,则线程数量太多就会耗尽内存。
- 线程数量太多,则线程间的频繁切换上下文切换又极大的浪费CPU资源。
- 线程大量死亡后又会造成频繁GC。
线程池通过线程复用则极大的节省了系统资源。
JVM内存模型
Java内存模型是围绕着并发过程中如何处理原子性、可见性、有序性这三个特征来建立的
- 共享变量存储在主内存中
- 每个线程有自己的工作内存
- 工作内存中保存了该共享变量的副本
- 线程对变量的读写必须在工作内存中进行
-
线程A无法直接访问线程B工作内存的变量,A和B间变量值的传递需要通过主内存来完成。
JMM.png
CountDownLatch、CyclicBarrier、Semaphore
CountDownLatch:一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
CyclicBarrier:一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
Semaphore:可以控制同时访问的线程个数,Semaphore与 Lock 的区别就是 Lock 只能是一个锁,而 Semaphore 更像是多个锁的一个集合,像一个阻塞队列一样,当队列中的锁用完了,而你又需要锁的时候,你就必须等待其他的线程释放锁。
网友评论