线程安全原因:

1.共享数据

2.多条线程操作共享数据

 

在java中关键字synchronized可以保证同一时刻只有一个线程可以执行某个方法或某个方法块,同时保证一个线程的变化可以被其他线程看到

锁就是一个类似于队列的数据结构,当有多个线程并发访问对象时,如果对象已经被其他线程锁定,那么当前线程会有一个入队的操作,同步操作的实现,需要给对象关联一个互斥体,这个互斥体就可以叫做锁

互斥锁:当存在多个数据操作共享数据时,需要保证有且仅有一个线程在操作共享数据,其他线程必须等该线程处理完数据后才能执行

悲观锁:一个线程加锁后,使得该对象成为该线程的多有对象,其他线程只能悲观锁阻拦在外,无法操作

乐观锁:认为多个线程一个对象的操作不会冲突,所有不加锁,只是在提交更改时验证是否冲突,若冲突则重试知道成功(尝试过程称为自旋)

 

线程五种状态: 

go java并发 java高并发详解_线程池

 

CAS

执行函数:CAS(V,E,N)

go java并发 java高并发详解_go java并发_02

先获得原值prev和要改成的新值next,当CAS替换新值不成功时,自旋重新获得原值prev和新值next再试一次

public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

 

多线程锁

1.无锁

没有对资源锁定,所有线程都能访问并修改资源,但同时只能又一个修改成功,其他线程通过CAS自旋不断尝试

2.偏向锁

偏向第一个加锁线程,该线程不会主动释放偏向锁,只有当其他线程竞争偏向锁才会释放

偏向锁的撤销,当某个时间点没有字节码执行时

       a.暂停偏向锁的线程

       b.判断对象是否处于被锁定状态

       c.i:如果线程不处在活动状态,则将对象头设置成无所状态,并撤销偏向锁

       c.ii:如果线程处在活动状态,则升级为轻量级锁状态

3.轻量级锁

 当锁时偏向锁时,被第二个线程B访问,则偏向锁会升级为轻量级锁,线程B会以自旋方式获取锁

4.重量级锁

当又一个线程获取锁后,其余所有等待获取该锁的线程处于阻塞状态

当自旋数量达到一定数量时,轻量级锁会升级为重量级锁;

当超过两个线程在自旋等待获取锁,轻量级锁也会升级为重量级锁(阻塞了)

 

线程池

线程池的五种状态:

1.RUNNING(runing)

表示线程池正在运行中,可以正常的接受并处理任务

2.SHUTDOWN(shutdown)

表示线程池关闭了,不能接受新任务,但是线程池会把阻塞队列中的剩余任务执行完,剩余任务处理完之后们会中断所有线程

3.STOP(stop)

也表示线程关闭了,不能接受新任务,但是并不会处理阻塞队列中剩下的任务,会直接中断线程

4.TIDYING(tidying)

当线程中没有没有工作线程在运行之后就会进入TIDYING状态

5.TERMINATED(terminated)

线程池处于TIDYING状态后,会执行terminated()方法,执行完成后就会进入TERMINATED状态

另外,在ThreadPoolExecutor中terminated()方法是一个空方法,可以自定义线程池重写这个方法,来定义线程池关闭完成需要执行的逻辑

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

go java并发 java高并发详解_java_03

 

 Executors类线程池:

go java并发 java高并发详解_线程池_04

go java并发 java高并发详解_线程池_05

go java并发 java高并发详解_线程池_06

go java并发 java高并发详解_System_07

go java并发 java高并发详解_线程池_08

go java并发 java高并发详解_System_09

go java并发 java高并发详解_java_10

go java并发 java高并发详解_java_11

 代码实例

package com.guor.thread;
 
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
public class Handle implements Runnable {
    private String name;
 
    public Handle(String name) {
        this.name = "Thread" + name;
    }
 
    @Override
    public void run() {
        System.out.println(name + "-> start time : " + new Date());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "-> end time : " + new Date());
    }
 
    public static void main(String[] args) throws InterruptedException {
        scheduledTest();
    }
 
    //可缓存的线程池
    private static void cacheTest() {
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            Handle handle = new Handle(String.valueOf(i));
            newCachedThreadPool.execute(handle);
        }
        newCachedThreadPool.shutdown();
        System.out.println("Main Thread: Finished at:" + new Date());
    }
 
    //固定长度的线程池
    private static void fixedTest() {
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Handle handle = new Handle(String.valueOf(i));
            newFixedThreadPool.execute(handle);//先执行五个,然后再执行五个
        }
        newFixedThreadPool.shutdown();
        System.out.println("Main Thread: Finished at:" + new Date());
    }
 
    //单线程线程池
    private static void singleTest() {
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            Handle handle = new Handle(String.valueOf(i));
            newSingleThreadExecutor.execute(handle);//单一线程分次执行
        }
        newSingleThreadExecutor.shutdown();
        System.out.println("Main Thread: Finished at:" + new Date());
    }
 
    /**
     * 固定长度的线程池,而且以延迟或者定时的方式来执行,类似Timer
     *
     * scheduleAtFixedRate 按指定频率周期执行某个任务
     * scheduleAtFixedRate ,是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕,
     * 如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。
     *
     * scheduleWithFixedDelay 周期定时执行某个任务/按指定频率间隔执行某个任务(注意)
     * scheduleWithFixedDelay,是以上一个任务结束时开始计时,period时间过去后,立即执行。
     *
     */
    private static void scheduledTest() {
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(10);
        for (int i = 0; i < 3; i++) {
            Handle handle = new Handle(String.valueOf(i));
            //执行
            //newScheduledThreadPool.execute(handle);
            //延迟1秒执行
            //newScheduledThreadPool.schedule(handle, 1, TimeUnit.SECONDS);
            //延迟1秒,每隔3秒执行一遍(隔3秒执行,①如果上一次结束,立即执行;②如果上一次未结束,结束立即执行;)
            //newScheduledThreadPool.scheduleAtFixedRate(handle, 1, 3, TimeUnit.SECONDS);
            //延迟1秒,每隔3秒执行一遍(上一个任务结束开始计时)
            newScheduledThreadPool.scheduleWithFixedDelay(handle, 1, 3, TimeUnit.SECONDS);
        }
        //newScheduledThreadPool.shutdown();
        System.out.println("Main Thread: Finished at:" + new Date());
    }
}

Calltable开启多线程

package com.guor.thread;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
 
public class TaskWithResult implements Callable<String> {
    private int id;
 
    public TaskWithResult(int id) {
        this.id = id;
    }
 
    @Override
    public String call() throws Exception {
        System.out.println("call()方法被自动调用,干活!!!             " + Thread.currentThread().getName());
        Thread.sleep(2000);
        return "call()方法被自动调用,任务的结果是:" + id + "    " + Thread.currentThread().getName();
    }
 
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        List<Future<String>> list = new ArrayList<Future<String>>();
        // 创建10个任务并执行
        for (int i = 0; i < 10; i++) {
            //使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
            Future<String> future = newCachedThreadPool.submit(new TaskWithResult(i));
            //将任务执行结果存储到List中
            list.add(future);
        }
 
        //启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
        newCachedThreadPool.shutdown();
        for(Future<String> future : list) {
            System.out.println(future.get() + "--date--> " +new Date());
        }
    }
}