摘要
- Java线程同步与异步
- 线程池
- 无锁化的实现方案
- 分布式的实现方案
Java线程同步与异步
1、同步相关的方法有:
- wait、notify、notifyAll
2、关键字:
- Synchronized
3、JDK锁框架
- AQS(AbstractQueuedSynchronizer)
4、AQS的实现类
- java.util.concurrent.locks.ReentrantLock
- java.util.concurrent.locks.ReentrantReadWriteLock
- java.util.concurrent.CountDownLatch
- java.util.concurrent.Semaphore
5、例子:两个线程交替打印出100以内的奇数和偶数
public class SynchronizedTest{
private static int cnt = 1;
public static void main(String[] args){
MyThread myThread = new MyThread();
Thread thread1 = new Thread(myThread);
Thread thread2 = new Thread(myThread);
thread1.start();
thread2.start();
try{
thread1.join();
thread2.join();
}catch(InterruptedException e){
e.printStackTrace();
}
}
priavte static class MyThread implements Runnable{
@Override
public void run(){
while(true){
synchronized(this){
this.notify();
if(cnt <=20){
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + ":" + cnt++);
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}else{
return ;
}
}
}
}
}
}
输出结果: 还可以使用两种其他方法实现,加深自己对Java线程同步和互斥的理解!
线程池
- 作用:控制线程并发数量,一般用在控制单机并发度上,也是实现流控的一种方案;
- 实现原理:
1、参数含义
- corePoolSize:核心线程的数量,在CPU密集和IO密集型的任务中,这个参数的设置不太一样
- maximumPoolSize:最大核心线程的数量
- poolSize:当前线程的数量
2、当用户向线程池中新提交一个线程的时候,会出现如下情况:
- 如果当前线程池中线程的数量小于corePoolSize, 就会创建一个新的线程, 并添加到线程池中;
- 如果当前线程池中线程的数量等于corePoolSize, 并且等待队列中还没有满,则把当前用户添加的线程对象放在等待队列中;
- 如果当前线程池中线程的数量大于等于corePoolSize并且小于maximunPoolSize,并且等待队列已经满,则创建一个新的线程,并添加到线程池中;
- 如果当前线程池中线程的数量等于maximunPoolSize, 则会根据线程创建线程时候的拒绝策略,进行相应的处理;
3、Java线程对象中run方法和start方法区别:
- 线程对象直接调用run方法,JVM是不会有感知,是不会直接产生一个新的线程, 此时程序运行的方式依然是串行的;
- 线程对象直接调用start方法,JVM才会有感知,会产生一个新的线程, 此时才会产生并发多线程; 线程池正是充分利用了run方法和start的区别来实现线程的复用;
线程池的核心代码
public void execute(Runnable command){
if(command == null)
throw new NullPointerException();
if(poolSize >= corPoolSize || !addIfUnderCorePoolSize(command)){
if(runState == RUNNING && workQueue.offer(command)){
if(runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
else if(!addIfUnderMaxmumPoolSize(command))
reject(command);
}
}