美文网首页
Java并发编程

Java并发编程

作者: DaemonXiao | 来源:发表于2019-04-27 20:48 被阅读0次

余学习Java一年有余,然懵懵懂懂不得精髓,盖懒惫不肯专研,又或三天打渔两天晒网不能坚持。今习并发编程,愿持之以恒,悟得妙法。

Java内存模型——同步的八种操作

  1. use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎。
  2. assign(赋值):作用于工作内存的变量,把一个从执行引擎接收到的值赋给工作内存的变量。
  3. store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传递到主内存中,以便于以后的write操作。
  4. write(写入):作用于主内存的变量,把store操作从工作内存中的一个变量的值传递到主内存的变量中。
  5. lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
  6. unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其它线程锁定。
  7. read(读取):作用于主内存的变量,把一个变量值从主内存传输到工作线程的工作内存中,以便以后的load动作使用。
  8. 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();
            }
        }
    }
}

未完待续。。。

相关文章

网友评论

      本文标题:Java并发编程

      本文链接:https://www.haomeiwen.com/subject/alklnqtx.html