1. 生产者与消费者
1.1 安全问题产生
-  线程本身就是一个新创建的方法栈内存 (CPU进来读取数据) 
-  线程的notify(),唤醒第一个等待的线程 -  解决办法 : 全部唤醒 notifyAll() 
 
-  
-  被唤醒线程,已经进行过if判断,一旦醒来继续执行 -  线程被唤醒后,不能立刻就执行,再次判断标志位,利用循环 
-  while(标志位) 标志位是true,永远也出不去 
 
-  
/**
 * 定义资源对象
 *   成员 : 产生商品的计数器
 *          标志位
 */
public class Resource {
   private int count ;
   private boolean flag ;
   //消费者调用
   public synchronized void getCount() {
         //flag是false,消费完成,等待生产
         while (!flag)
            //无限等待
            try{this.wait();}catch (Exception ex){}
         System.out.println("消费第"+count);
            //修改标志位,为消费完成
         flag = false;
         //唤醒对方线程
         this.notifyAll();
   }
   //生产者调用
   public synchronized void setCount() {
         //flag是true,生产完成,等待消费
       while (flag)
            //无限等待
            try{this.wait();}catch (Exception ex){}
         count++;
         System.out.println("生产第"+count+"个");
         //修改标志位,为生产完成
         flag = true;
         //唤醒对方线程
         this.notifyAll();
   }
}/**
 * 生产者线程
 *   资源对象中的变量++
 */
public class Produce implements Runnable{
    private Resource r ;
    public Produce(Resource r) {
        this.r = r;
    }
    @Override
    public void run() {
        while (true) {
            r.setCount();
        }
    }
}/**
 * 消费者线程
 *   资源对象中的变量输出打印
 */
public class Customer implements Runnable{
    private Resource r ;
    public Customer(Resource r) {
        this.r = r;
    }
    @Override
    public void run() {
        while (true) {
            r.getCount();
        }
    }
}    public static void main(String[] args) {
        Resource r = new Resource();
        //接口实现类,生产的,消费的
        Produce produce = new Produce(r);
        Customer customer = new Customer(r);
        //创建线程
        new Thread(produce).start();
        new Thread(produce).start();
        new Thread(produce).start();
        new Thread(produce).start();
        new Thread(produce).start();
        new Thread(produce).start();
        new Thread(customer).start();
        new Thread(customer).start();
        new Thread(customer).start();
        new Thread(customer).start();
        new Thread(customer).start();
        new Thread(customer).start();
    }
1.2 线程方法sleep和wait的区别
-  sleep()在休眠的过程中,同步锁不会丢失 ,不释放 
-  wait()等待的时候,发布监视器的所属权, 释放锁.唤醒后要重新获取锁,才能执行 
1.3 生产者和消费者案例性能问题
wait()方法和notify()方法, 本地方法调用OS的功能,和操作系统交互,JVM找OS,把线程停止. 频繁等待与唤醒,导致JVM和OS交互的次数过多.
notifyAll()唤醒全部的线程,也浪费线程资源,为了一个线程,不得以唤醒的了全部的线程.
1.4 Lock接口深入
Lock接口替换了同步synchronized, 提供了更加灵活,性能更好的锁定操作
-  Lock接口中方法 : newCondition() 方法的返回值是接口 : Condition 

1.5 生产者与消费者改进为Lock接口
-  Condition接口 (线程的阻塞队列) -  进入队列的线程,释放锁 
-  出去队列的线程,再次的获取锁 
-  接口的方法 : await() 线程释放锁,进入队列 
-  接口的方法 : signal() 线程出去队列,再次获取锁 
 
-  
线程的阻塞队列,依赖Lock接口创建
/**
 *  改进为高性能的Lock接口和线程的阻塞队列
 */
public class Resource {
   private int count ;
   private boolean flag ;
   private Lock lock = new ReentrantLock();//Lock接口实现类对象
    //Lock接口锁,创建出2个线程的阻塞队列
    private Condition prod = lock.newCondition();//生产者线程阻塞队列
    private Condition cust = lock.newCondition();//消费者线程阻塞队列
   //消费者调用
   public  void getCount() {
       lock.lock();//获取锁
         //flag是false,消费完成,等待生产
         while (!flag)
            //无限等待,消费线程等待,执行到这里的线程,释放锁,进入到消费者的阻塞队列
             try{cust.await();}catch (Exception ex){}
         System.out.println("消费第"+count);
            //修改标志位,为消费完成
         flag = false;
         //唤醒生产线程队列中的一个
         prod.signal();
         lock.unlock();//释放锁
   }
   //生产者调用
   public  void setCount() {
       lock.lock();//获取锁
         //flag是true,生产完成,等待消费
       while (flag)
            //无限等待,释放锁,进入到生产线程队列
            try{prod.await();}catch (Exception ex){}
         count++;
         System.out.println("生产第"+count+"个");
         //修改标志位,为生产完成
         flag = true;
         //唤醒消费者线程阻塞队列中年的一个
         cust.signal();
       lock.unlock();//释放锁
   }
}1.6 Lock锁的实现原理
使用技术不开源,技术的名称叫做轻量级锁
使用的是CAS锁 (Compare And Swap) 自旋锁
JDK限制 : 当竞争的线程大于等于10,或者单个线程自旋超过10次的时候
JDK强制CAS锁取消.升级为重量级锁 (OS锁定CPU和内存的通信总线,只有一个线程通过)

2. 单例设计模式
设计模式 : 不是技术,是以前的人开发人员,为了解决某些问题实现的写代码的经验.
所有的设计模式核心的技术,就是面向对象.
Java的设计模式有23种,分为3个类别,创建型,行为型,功能型
(此博客中单例模式)
Java-设计模式-(三)单例模式(创建型模式)_YounG_tt33的博客-CSDN博客
2.3 关键字volatile
成员变量修饰符,不能修饰其它内容
-  关键字作用 : -  保证被修饰的变量,在线程中的可见性 
-  防止指令重排序 -  单例的模式, 使用了关键字,不使用关键字,可能线程会拿到一个尚未初始化完成看的对象(半初始化) 
 
-  
 
-  
3. 线程池ThreadPool
线程的缓冲池,目的就是提高效率. new Thread().start() ,线程是内存中的一个独立的方法栈区,JVM没有能力开辟内存空间,和OS交互. (缓冲池技术)
JDK5开始内置线程池 类比数据库连接池(Connection)
3.1 Executors类
-  静态方法static newFixedThreadPool(int 线程的个数) 输入int后创建线程池固定,扩容则会创建新的线程池 -  方法的返回值ExecutorService接口的实现类,管理池子里面的线程 
 
-  
-  ExecutorService接口的方法 -  submit (Runnable r)提交线程执行的任务 
 
-  
3.2 Callable接口
实现多线程的程序 : 接口特点是有返回值,可以抛出异常 (Runnable没有)
抽象的方法只有一个, call
启动线程,线程调用重写方法call
-  ExecutorService接口的方法 -  submit (Callable c)提交线程执行的任务 
-  Future submit()方法提交线程任务后,方法有个返回值 Future接口类型 
-  Future接口,获取到线程执行后的返回值结果 
 
-  
public class MyRunnable implements Runnable {
    @Override
    public void run() throws Exception{
        sout("线程开始启动");
    }
}public class MyCall implements Callable<String> {
    public String call() throws Exception{
        return "返回字符串";
    }
}    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程池,线程的个数是2个
       ExecutorService  es =  Executors.newFixedThreadPool(2);
       //线程池管理对象service,调用方法啊submit提交线程的任务
        MyRunnable my = new MyRunnable();
        //提交线程任务,使用Callable接口实现类
        Future<String> future = es.submit(new MyCall());//返回接口类型 Future
        //接口的方法get,获取线程的返回值
        String str = future.get();
        System.out.println("str = " + str);
//        es.submit(my);
//        es.submit(my);
//        es.submit(my);
       // es.shutdown();//销毁线程池
    }4. ConcurrentHashMap
ConcurrentHashMap类本质上Map集合,键值对的集合.使用方式和HashMap没有区别.
凡是对于此Map集合的操作,不去修改里面的元素,不会锁定
5. 线程的6种状态图-生命周期
在某一个时刻,线程只能处于其中的一种状态. 这种线程的状态反应的是JVM中的线程状态和OS无关.
 
 
TIMED_WAITING:sleep()与wait():sleep()不释放锁,时间结束后继续执行;wait()会释放锁,时间结束后wait()若拿不到锁会转为阻塞状态BLOCKED。
![[附源码]Python计算机毕业设计Django基于Vue的社区拼购商城](https://img-blog.csdnimg.cn/525699b6392b455e9675adeeafb328bd.png)








![[附源码]JAVA毕业设计霍山石斛网站(系统+LW)](https://img-blog.csdnimg.cn/44c7493604a044b9a180df4dd1f36777.png)









