1.线程安全的集合类
利用CAS算法 比较交换算法 无锁算法
(1)CopyOnWriteArrayList
利用复制数组的方式实现数据的写操作,读操作不用加锁
(适用于读操作频率远高于写操作的情况)
(2)ConcurrenHashMap(since 1.5)
实现方法:
JDK5-7:分段锁 将HashMap分割成16段,每段(segment)独立加锁
JDK8:使用CAS无锁算法,使用循环比较算法
(3)ConcurrentLinkedQueue
利用CAS算法,实现线程安全
offer():放入
poll():拿出
2.原子操作数据类型 (避免出现线程的不安全)
AtomicInteger 原子整数
AtomicBoolean原子布尔
AtomicLong原子长整数 等。。。
以上原子操作数所在java.lang.Number中
3.ForkJoin框架(since 1.7)
核心思想:利用递归将任务分解为若干个子任务,交给多线程去并发处理
用途:多用于多核cpu并发
继承类:RecursiveAction(无返回值)、RecursiveTask(有返回值)
任务代码:compute()方法
ForkJoinPool:线程池 固定的线程数量:cpu的核数
工作窃取算法(早干完替耗时长的做任务):
当一个cpu内核结束所有任务时,会从其他的cpu内核的任务队列中“窃取”一个任务来执行,返回最大的并发性能。
(1)ForkJoinAction(代码实现)
package review.test;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinActionTest01 {
public static void main(String[] args) {
String[] data = new String[10000];
for (int i = 0; i < data.length; i++) {
data[i] = "abcd" + i;
}
ForkJoinPool fjp = new ForkJoinPool();
RecursiveAction ra = new NewAction(data ,0 , data.length);
fjp.invoke(ra);
}
}
class NewAction extends RecursiveAction{
String[] data;
int start;
int end;
public NewAction(){}
public NewAction(String[] data,int start,int end){
this.data = data;
this.start = start;
this.end = end;
}
public void compute(){
if(end - start <= 100){
for (int i = start ; i < end; i++) {
data[i].toUpperCase();
}
}else{
int middle = (start + end)/2;
NewAction leftAction = new NewAction(data,start,middle);
NewAction rightAction = new NewAction(data,middle, end);
leftAction.fork();
rightAction.compute();
leftAction.join();
}
}
}
(2)ForkJoinTask(代码实现)
package review.test;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class ForkJoinTaskTest01 {
public static void main(String[] args) {
int[] data = new int[5000];
for (int i = 0; i < data.length; i++) {
data[i]+=100+i;
}
ForkJoinPool pool = new ForkJoinPool();
Integer result = (Integer) pool.invoke(new NewTask(data,0,data.length));
System.out.println(result);
pool.shutdown();
}
}
class NewTask extends RecursiveTask{
int[] data;
int start;
int end;
public NewTask(){}
public NewTask(int[] data,int start,int end){
this.data = data;
this.start = start;
this.end = end;
}
public Integer compute(){
if(end - start <= 100){
int max = data[0];
for (int i = 0; i < data.length; i++) {
if(data[i] > max){
max = data[i];
}
}return max;
}else{
int middle = (start + end)/2;
NewTask leftTask = new NewTask(data,start,middle);
NewTask rightTask = new NewTask(data,middle,end);
leftTask.fork();
Integer rightResult = rightTask.compute();
Integer leftResult = (Integer) leftTask.join();
if(rightResult > leftResult){
return rightResult;
}else{
return leftResult;
}
}
}
}
4.等待通知机制 (线程间通信)
Object类:定义了wait() notify() notifyAll()
①wait():必须在对o加锁的同步代码块中,对o调用wait()
线程会释放其拥有的所有锁标记
线程会阻塞在对象o的等待队列中
②notify()/notifyall():
必须在对o加锁的同步代码块中,对o调用notify()/notifyAll()
线程会从o的等待队列中,释放一个或者全部线程
package day27;
public class TestWaitNotify {
public static void main(String[] args) throws Exception{
Object o = new Object();
System.out.println("main 1");
Thread t = new Thread(){
public void run(){
synchronized (o) {
System.out.println("thread 1");
o.notify();
System.out.println("thread 2");
}
}
};
t.start();
synchronized (o) {
o.wait();
System.out.println("main 2");
}
}
}
5.生产者消费者问题
当生产者无法生产时,消费者等待
当消费者无法消费时,生产者等待
BlockingQueue Queue接口的子接口 阻塞队列 接口
1.ArrayBlockingQueue 有界队列
当消费者无法消费时会阻塞,当生产者无法生产时会阻塞
2.LinkedBlockingQueue 无界队列
当消费者无法消费时会阻塞
package day27;
public class TestProducerConsumer {
public static void main(String[] args) {
MyStack stack = new MyStack();
Thread t1 = new Thread(){
public void run(){
for(int i = 1 ; i <= 100 ; i++){
stack.push("A"+i);
stack.print();
}
}
};
t1.start();
Thread t2 = new Thread(){
public void run(){
for(int i = 1 ; i <= 100 ; i++){
stack.pop();
stack.print();
}
}
};
t2.start();
}
}
class MyStack{
private String[] data = new String[5];
private int index;
public synchronized void push(String str){
while(data.length == index){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str+" pushed into stack ");
data[index] = str;
index++;
this.notifyAll();
}
public synchronized void pop(){
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index--;
System.out.print(data[index]+" poped out of stack ");
data[index] = " ";
this.notifyAll();
}
public void print(){
for(int i = 0 ; i < data.length; i++) System.out.print(data[i]+" ");
System.out.println();
}
}
5.多线程自动启用流
parallelstream()
等同于:toStream()
基于Fork-join框架
面试题:
wait()与sleep()的区别:
wait会释放锁标记
sleep不会释放锁标记