CoreJava基础之多线程(线程安全的集合类,ForkJoin框架)

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不会释放锁标记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员巨轮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值