什么是协程?

一、什么是协程?

           对操作系统来说:

             1)线程是最小的【执行单元】

             2)进程是最小的【资源管理单元】

           

二、Java中线程具有5种状态

           1、初始化

           2、可运行

           3、运行中

           4、阻塞

           5、销毁

什么是协程?_第1张图片

线程不同状况之间的转化是谁来实现的呢?

   是JVM吗?

      并不是。JVM需要通过操作系统内核中的【TCB】(Thread Control Block)模块来改变线程的状态,这一过程需要【耗费一定的CPU资源】。

 

三、进程和线程的痛点?

          1、线程之间是如何进行【协作】的呢?

                ①. 最经典的例子就是【生产者/消费者模式】

                ②. 若干个生产者线程向队列中写入数据
                      若干个消费者线程从队列中消费数据。

                  什么是协程?_第2张图片

如何用java语言实现生产者/消费者模式呢?

public class Producer extends Thread{

   private static final int MAX_QUEUE_SIZE = 5;

   private final Queue sharedQueue;

    public Producer (Queue sharedQueue) {
        super();
        this.sharedQueue = sharedQueue;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
           synchronized(sharedQueue){
              while(sharedQueue.size() >= MAX_QUEUE_SIZE){
                  System.out.println("队列满了,等待消费");
                  try {
                      sharedQueue.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
               sharedQueue.add(i);
               System.out.println("进行生产 : " + i);
               sharedQueue.notify();
           }

        }
    }
}

 

 
 
   public class Consumer extends Thread{

    private final Queue sharedQueue;

    public Consumer (Queue sharedQueue) {
        super();
        this.sharedQueue = sharedQueue;
    }

    @Override
    public void run() {
       while(true){
          synchronized(sharedQueue){
              while(sharedQueue.size() == 0){
                  System.out.println("队列空了,等待生产");
                  try {
                      sharedQueue.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              int number = (int) sharedQueue.poll();
              System.out.println("进行消费 : "+ number );
              sharedQueue.notify();
          }

       }
    }
}

 

 
 
    public class ProducerConsumerTest {

    public  static  void main(String  args[]) {
        final Queue sharedQueue = new  LinkedList();
        Thread producer = new Producer(sharedQueue);
        Thread consumer = new Consumer (sharedQueue);
        producer.start();
        consumer.start();
    }
}

 

------------------------------------输出结果:
进行生产 : 0
进行生产 : 1
进行生产 : 2
进行生产 : 3
进行生产 : 4
队列满了,等待消费
进行消费 : 0
进行消费 : 1
进行消费 : 2
进行消费 : 3
进行消费 : 4
队列空了,等待生产
进行生产 : 5
进行生产 : 6
进行生产 : 7
进行生产 : 8
进行生产 : 9
队列满了,等待消费
进行消费 : 5
进行消费 : 6
进行消费 : 7
进行消费 : 8
进行消费 : 9
队列空了,等待生产
进行生产 : 10
进行生产 : 11
进行生产 : 12
进行生产 : 13
进行生产 : 14
队列满了,等待消费
进行消费 : 10
进行消费 : 11
进行消费 : 12
进行消费 : 13
进行消费 : 14
队列空了,等待生产
进行生产 : 15
进行生产 : 16
进行生产 : 17
进行生产 : 18
进行生产 : 19
队列满了,等待消费
进行消费 : 15
进行消费 : 16
进行消费 : 17
进行消费 : 18
进行消费 : 19
队列空了,等待生产
进行生产 : 20
进行生产 : 21
进行生产 : 22
进行生产 : 23
进行生产 : 24
队列满了,等待消费
进行消费 : 20
进行消费 : 21
进行消费 : 22
进行消费 : 23
进行消费 : 24
队列空了,等待生产
进行生产 : 25
进行生产 : 26
进行生产 : 27
进行生产 : 28
进行生产 : 29
队列满了,等待消费
进行消费 : 25
进行消费 : 26
进行消费 : 27
进行消费 : 28
进行消费 : 29
队列空了,等待生产
进行生产 : 30
进行生产 : 31
进行生产 : 32
进行生产 : 33
进行生产 : 34
队列满了,等待消费
进行消费 : 30
进行消费 : 31
进行消费 : 32
进行消费 : 33
进行消费 : 34
队列空了,等待生产
进行生产 : 35
进行生产 : 36
进行生产 : 37
进行生产 : 38
进行生产 : 39
队列满了,等待消费
进行消费 : 35
进行消费 : 36
进行消费 : 37
进行消费 : 38
进行消费 : 39
队列空了,等待生产
进行生产 : 40
进行生产 : 41
进行生产 : 42
进行生产 : 43
进行生产 : 44
队列满了,等待消费
进行消费 : 40
进行消费 : 41
进行消费 : 42
进行消费 : 43
进行消费 : 44
队列空了,等待生产
进行生产 : 45
进行生产 : 46
进行生产 : 47
进行生产 : 48
进行生产 : 49
队列满了,等待消费
进行消费 : 45
进行消费 : 46
进行消费 : 47
进行消费 : 48
进行消费 : 49
进行生产 : 50
进行生产 : 51
进行生产 : 52
进行生产 : 53
进行生产 : 54
队列满了,等待消费
进行消费 : 50
进行消费 : 51
进行消费 : 52
进行消费 : 53
进行消费 : 54
队列空了,等待生产
进行生产 : 55
进行生产 : 56
进行生产 : 57
进行生产 : 58
进行生产 : 59
队列满了,等待消费
进行消费 : 55
进行消费 : 56
进行消费 : 57
进行消费 : 58
进行消费 : 59
队列空了,等待生产
进行生产 : 60
进行生产 : 61
进行生产 : 62
进行生产 : 63
进行生产 : 64
队列满了,等待消费
进行消费 : 60
进行消费 : 61
进行消费 : 62
进行消费 : 63
进行消费 : 64
队列空了,等待生产
进行生产 : 65
进行生产 : 66
进行生产 : 67
进行生产 : 68
进行生产 : 69
队列满了,等待消费
进行消费 : 65
进行消费 : 66
进行消费 : 67
进行消费 : 68
进行消费 : 69
队列空了,等待生产
进行生产 : 70
进行生产 : 71
进行生产 : 72
进行生产 : 73
进行生产 : 74
队列满了,等待消费
进行消费 : 70
进行消费 : 71
进行消费 : 72
进行消费 : 73
进行消费 : 74
队列空了,等待生产
进行生产 : 75
进行生产 : 76
进行生产 : 77
进行生产 : 78
进行生产 : 79
队列满了,等待消费
进行消费 : 75
进行消费 : 76
进行消费 : 77
进行消费 : 78
进行消费 : 79
队列空了,等待生产
进行生产 : 80
进行生产 : 81
进行生产 : 82
进行生产 : 83
进行生产 : 84
队列满了,等待消费
进行消费 : 80
进行消费 : 81
进行消费 : 82
进行消费 : 83
进行消费 : 84
队列空了,等待生产
进行生产 : 85
进行生产 : 86
进行生产 : 87
进行生产 : 88
进行生产 : 89
队列满了,等待消费
进行消费 : 85
进行消费 : 86
进行消费 : 87
进行消费 : 88
进行消费 : 89
队列空了,等待生产
进行生产 : 90
进行生产 : 91
进行生产 : 92
进行生产 : 93
进行生产 : 94
队列满了,等待消费
进行消费 : 90
进行消费 : 91
进行消费 : 92
进行消费 : 93
进行消费 : 94
队列空了,等待生产
进行生产 : 95
进行生产 : 96
进行生产 : 97
进行生产 : 98
进行生产 : 99
进行消费 : 95
进行消费 : 96
进行消费 : 97
进行消费 : 98
进行消费 : 99
队列空了,等待生产

这段代码做了下面几件事:
  1.定义了一个生产者类,一个消费者类。
  2.生产者类循环100次,向同步队列当中插入数据。
  3.消费者循环监听同步队列,当队列有数据时拉取数据。
  4.如果队列满了(达到5个元素),生产者阻塞。
  5.如果队列空了,消费者阻塞。

 

上面的代码正确地实现了生产者/消费者模式,但是却并不是一个高性能的实现。
为什么性能不高呢?原因如下: 

   1. 涉及到同步锁

   2. 涉及到线程阻塞状态和可运行状态之间的切换

   3. 涉及到线程上下文的切换

   以上涉及到的任何一点,都是非常耗费性能的操作。

这个时候【协程】就登场了

 

四、到底什么是【协程】?

        协程,英文Coroutines,是一种比【线程】更加【轻量级】的存在。

        正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。

        什么是协程?_第3张图片

      最重要的是,【协程】不是被操作系统【内核】所管理的,而完全是由【程序】所控制(也就是在【用户态】执行)

      这样带来的好处就是:

          性能得到了很大的提升,不会像线程切换那样消耗资源。

 

五、既然协程这么好,它到底是怎么来使用的呢?

          由于Java的原生语法中并没有实现协程(某些开源框架实现了协程,但是很少被使用)

          协程的开销远远小于线程的开销。

 

六、协程的应用

Java语言
   如上文所说,Java语言并没有对协程的原生支持,但是某些开源框架模拟出了协程的功能,有兴趣的小伙伴可以看一看Kilim框架的源码:
  https://github.com/kilim/kilim

 

你可能感兴趣的:(协程)