Java并发编程
2019-04-27 本文已影响0人
DaemonXiao
余学习Java一年有余,然懵懵懂懂不得精髓,盖懒惫不肯专研,又或三天打渔两天晒网不能坚持。今习并发编程,愿持之以恒,悟得妙法。
Java内存模型——同步的八种操作
- use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎。
- assign(赋值):作用于工作内存的变量,把一个从执行引擎接收到的值赋给工作内存的变量。
- store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传递到主内存中,以便于以后的write操作。
- write(写入):作用于主内存的变量,把store操作从工作内存中的一个变量的值传递到主内存的变量中。
- lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
- unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其它线程锁定。
- read(读取):作用于主内存的变量,把一个变量值从主内存传输到工作线程的工作内存中,以便以后的load动作使用。
- load(载入):作用于工作内存的变量,把read操作从主内存中得到的变量值放入工作内存的变量副本中。
同步规则
- 如果要把一个变量从主内存中复制到工作内存,就需要按顺序地执行read和load操作,如果把变量从工作内存中同步到主内存中,就要按顺序地执行stroe和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。
- 不允许read和load、store和write操作之一单独出现。
- 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须同步到主内存中。
- 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步到主内存中。
- 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或者assign)的变量。即就是对一个变量实施use和store操作之前必须先执行assgin和load操作。
- 一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。lock和unlock必须成对出现。
- 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始变化量的值。
- 如果一个变量事先没有被lock锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
-
对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。
Java线程池
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
public class MyThreadPool {
//1.需要一个仓库
private BlockingQueue<Runnable> blockingQueue;
//2. 一个线程的集合
private List<Thread> workers;
//3. 一个人干活
public static class Worker extends Thread {
private MyThreadPool pool;
public Worker(MyThreadPool pool) {
this.pool = pool;
}
@Override
public void run() {
while (this.pool.isWorking || this.pool.blockingQueue.size() > 0) {
Runnable task = null;
try {
if(this.pool.isWorking)
task = this.pool.blockingQueue.take();
else
task = this.pool.blockingQueue.poll();
} catch (Exception e) {
e.printStackTrace();
}
if (task != null) {
task.run();
System.out.println("线程:" + Thread.currentThread().getName() + "执行完毕");
}
}
}
}
//4.初始话线程池
public MyThreadPool(int poolSize, int taskSize) {
if (poolSize <= 0 || taskSize <= 0) {
throw new IllegalArgumentException("非法参数");
}
this.blockingQueue = new LinkedBlockingQueue<>(taskSize);
this.workers = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < poolSize; i++) {
Worker worker = new Worker(this);
worker.start();
workers.add(worker);
}
}
//5. 向仓库中放任务(非阻塞)
public boolean submit(Runnable task) {
if (isWorking) {
return this.blockingQueue.offer(task);}
return false;
}
//6. 向仓库中放任务(阻塞)
public void execute(Runnable task) {
if (isWorking){
try {
this.blockingQueue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//7. 关闭
//关闭的时候,仓库停止有新的任务进来
//关闭的时候,仓库如果还有东西要执行完毕
//关闭的时候,如果再去仓库拿东西,就不能阻塞了
//关闭的时候,如果还有线程被阻塞,要强行中断
private volatile boolean isWorking = true;
public void shutDown() {
isWorking = false;
for (Thread thread : workers) {
if (thread.getState().equals(Thread.State.WAITING) ||
thread.getState().equals(Thread.State.BLOCKED)) {
thread.interrupt();
}
}
}
}
未完待续。。。