设为首页 加入收藏

TOP

用java实现操作系统的前趋图
2019-05-11 14:28:35 】 浏览:52
Tags:java 实现 操作系统
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gao23191879/article/details/75123213

学过操作系统的人都知道前驱图是一个很好用来描述多个进程或线程间的同步执行的过程
科普一下同步的概念:同步是用来描述多个并发线程或进程按某种规则共享系統资源,并能很好的相互协作,使程序执行具有可再现性。
首先我们来看一下最简单的前趋图
这里写图片描述
java如何实现了
有俩种方式
第一种基于Lock+Condition方式

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {

    public static void main(String[] args) {
        //创建一个固定的线程池
         ExecutorService es=Executors.newFixedThreadPool(4);
         //创建一个锁
         final Lock lock=new ReentrantLock();
         //创建一个条件S
         final  Condition s=lock.newCondition();
         //我们调一下主线程的执行顺序  p2->p1
         //理想输出结果为 p1->p2
          es.execute(new Runnable(){

            @Override
            public void run() {
                 lock.lock();
             try{
                 try {
                //阻塞等待信号量的通知
                    s.await();
                  //当前线程要处理的功能代码,在这里我只简单输出一句话
                  System.out.println("我是p2线程 ");

                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                 }finally{
                  lock.unlock();
                 }


            }

          });

          es.execute(new Runnable(){

            @Override
            public void run() {
                lock.lock();
                try{
                 //当前线程要处理的功能代码,在这里我只简单输出一句话
                   System.out.println("我是p1线程");
                   //通知等待线程
                    s.signal();
                }finally{
                    lock.unlock();

                }

            }

          });
    }

}

第二种基于java 计数信号量 Semaphore

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Test3 {
   public static void main(String[] args) {
        //创建一个固定的线程池
         ExecutorService es=Executors.newFixedThreadPool(4);
        //创建一个信号量初始化为0 ,使用公平竞争
         final Semaphore s=new Semaphore(0,true);
         //我们调一下主线程的执行顺序  p2->p1
         //理想输出结果为 p1->p2
          es.execute(new Runnable(){

            @Override
            public void run() {

              try {
              //执行后s=-1,线程阻塞等待
                s.acquire();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   
             //当前线程要处理的功能代码,在这里我只简单输出一句话
             System.out.println("我是p2线程");

            }

          });

          es.execute(new Runnable(){

            @Override
            public void run() {
           //当前线程要处理的功能代码,在这里我只简单输出一句话
             System.out.println("我是p1线程");
             //s=0; 即 阻塞队列的线程可以开始竞争
               s.release();

            }

          });
        }  
}

下面我们来看一下复杂的前趋图
这里写图片描述
根据操作系统知识可知 该前趋图的执行过程可以为:
p1->p2->p3->p4->p5->p6
定义7个信号量 :a,b,c,d,e,f,g都初始化为0
对应的处理任务为:s1->s2->s3->s4->s5->s6
p1={ s1 ; single(a); single(b) }
p2={ waite(a); s2; single(c); single(d) }
p3={ waite(b); s3; single(e) }
p4={ waite(c); s4; single(f); }
p5={ waite(d); s5; single(g); }
p6={ waite(e); waite(f); waite(g); s6;}
以上是操作系统的分析
waite() 时 信号量减一 说明该资源已被申请占用,因为初始化信号量为0 说明只能被一个线程请求使用,如果还有线程请求时将会阻塞,直到占用资源的线程释放该资源,并通知阻塞线程。此时阻塞队列中的线程将就绪,然后开始竞争。
下面我们来看一下java如何实现的
有以上分析可知p6线程需要等待三个信号量的通知才能执行。
而 java 条件监听机制 Condtion 一个线程只能等待一个通知信号,不能同时等待多个通知信号。
所以我们用java的计数信号量 Semaphore来实现
Semaphroe 类中有两方法 一个是 acquire() 等同于 waite()
release() 等同于 single()
下面我们来看一下代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
//java实现前驱图
public class Test2 {
    public static void main(String[] args) {
          //创建线程池
          ExecutorService es=Executors.newFixedThreadPool(10);
          //创建7个信号量
         final Semaphore a=new Semaphore(0,true);
         final Semaphore b=new Semaphore(0,true);
         final Semaphore c=new Semaphore(0,true);
         final Semaphore d=new Semaphore(0,true);
         final Semaphore e=new Semaphore(0,true);
         final Semaphore f=new Semaphore(0,true);
         final Semaphore g=new Semaphore(0,true);
         //我们打乱各线程在主线程的执行顺序,来更好的看一下执行效果
         es.execute(new Runnable(){

                @Override
                public void run() {
                         try {
                            a.acquire();
                            System.out.println("我来自S2");
                            c.release();
                            d.release();

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }


                }

              });
          es.execute(new Runnable(){

                @Override
                public void run() {
                         try {
                            e.acquire();
                            f.acquire();
                            g.acquire();
                            System.out.println("我来自S6");


                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }


                }

              });
          es.execute(new Runnable(){

            @Override
            public void run() {
                System.out.println("我来自S1");
                a.release();
                b.release();
            }
          });

          es.execute(new Runnable(){

                @Override
                public void run() {
                         try {
                            b.acquire();
                            System.out.println("我来自S3");
                            e.release();

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }


                }

              });
          es.execute(new Runnable(){

                @Override
                public void run() {
                         try {
                            c.acquire();
                            System.out.println("我来自S4");
                            f.release();

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }


                }

              });
          es.execute(new Runnable(){

                @Override
                public void run() {
                         try {
                            d.acquire();
                            System.out.println("我来自S5");
                            g.release();

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }


                }

              });

    }
}

执行结果如下
这里写图片描述
好了博客写完了,你有没有涨知识了。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇block,inline和inline-block概念.. 下一篇Spark Streaming运行kafka数据源

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目