Java基础学习之并发篇:哲学家就餐问题_哲学家问题 最大并发-程序员宅基地

技术标签: Java基础学习    java  并发编程  

学习目标

哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步时产生的问题。在1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份共享的磁带驱动器。稍后,这个问题被托尼·霍尔重新表述为哲学家就餐问题。这个问题可以用来解释死锁和资源耗尽

从百度百科上解释来看哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。总结来看哲学家问题就是:
在这里插入图片描述
接下来我们就将上述描述抽象出来,并用Java并发基础来解决哲学家就餐问题。


初步解决

针对上述问题我们可以简单定个协议规则:

  • 规则1:每个哲学家(线程)先拿起左边的叉子,再拿右边的叉子。
  • 规则2:如果拿不到就等待。

那么我可以抽象如下:

  • id(1-5)用来描述不同的哲学家
  • state三种状态:thinking、hungry、eating
  • 方法有拿起和放下叉子:takeLeft、takeRight、putLeft和putRight

那么我们可以得到如下程序:
哲学家抽象

/**
 * 哲学家抽象
 */
public class Philosopher implements Runnable{
   
    

    public String getState() {
   
    
        return state;
    }

    public void setState(String state) {
   
    
        this.state = state;
    }

    String state;
    int id;
    // 用来统计哲学家完成的次数
    int count = 0;
    // 用来统计总共完成的次数
    static AtomicInteger total = new AtomicInteger(0);
    // 开始时间
    static long startMills = System.currentTimeMillis();

    public Philosopher(int id){
   
    
        this.id = id;
        this.state = "Thinking";
    }

	/**
	 * 思考后状态是Hungry
	 */
    public void thinking() throws InterruptedException {
   
    
        if(this.state == "Thinking") {
   
    
            Thread.sleep((long)(Math.random()*100));
            this.state = "Hungry";
        }
    }
	/**
	 * 修改状态为Eating并模拟一段时间
	 */
    public void eating() throws InterruptedException {
   
    
        this.state = "Eating";
        if(Math.random() > 0.9) {
   
    
            Thread.sleep(100000);
        } else {
   
    
            Thread.sleep((long)(Math.random()*100));
        }
    }

    public int left(){
   
    
        return this.id - 1;
    }
    
    public int right(){
   
    
    // %5是因为哲学家id是从1-5,方便下标操作
        return this.id % 5;
    }

	/**
	 * 修拿起叉子需要判断当前叉子是否已被拿
	 */
    private boolean _take(int[] forks, int fork) {
   
    
        if(forks[fork] == 0) {
   
    
            forks[fork] = this.id;
            return true;
        }
        return false;
    }

    protected boolean takeLeft(int[] forks) {
   
    
        return this._take(forks, this.left());
    }
    protected boolean takeRight(int[] forks) {
   
    
        return this._take(forks, 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/h16407/article/details/121512226

智能推荐

linux - 自启动脚本_linux自启动脚本-程序员宅基地

文章浏览阅读3.2k次。自启动脚本**注:软件安装的路径和版本以及端口都是要根据服务器做相应的调整1.linux添加开机自启动单个服务程序脚本编写脚本autostart.sh(这里以开机启动redis服务为例),脚本内容如下:#!/bin/sh#chkconfig: 2345 80 90#description:开机自动启动的脚本程序开启redis服务 端口为6379/usr/local/service/redis-2.8.3/src/redis-server --port 6379 &脚本第一行 “#!/b_linux自启动脚本

Springboot2.X集成redis集群(Lettuce)连接的方法_springboot 2 redis 集群链接-程序员宅基地

文章浏览阅读4.4k次。前提:搭建好redis集群环境1.新建工程,pom.xml文件中添加redis支持<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></depen..._springboot 2 redis 集群链接

uboot和系统移植----------12、uboot 杂记 — logo 显示和 fastboot 原理_logo与fastbootlogo有什么差别-程序员宅基地

文章浏览阅读464次。一、x210 uboot 当中的LCD操作分析1、新旧版本开发板的LCD模组差异(1)2015.11月初之前购买的X210开发板都属于老版本,型号是 X210V3 ;之后购买的开发板都是新版本的,型号是X210V3S。(2)两个开发板主要电路是完全一样的,不同主要有3点:1、是把拨码开关换成了短路帽;2、另一个是LCD分辨率从800480升级成1024600;3、第三个是触摸屏芯片型号换了。2、背光电路分析(1)LCD的背光源有2种设计。一种是简单设计,背光只能点亮和熄灭两种状态,不能_logo与fastbootlogo有什么差别

Dubbo源码解析之服务调用过程-程序员宅基地

文章浏览阅读153次。简介在前面的文章中,我们分析了 Dubbo SPI、服务导出与引入、以及集群容错方面的代码。经过前文的铺垫,本篇文章我们终于可以分析服务调用过程了。Dubbo 服务调用过程比较复杂,包含众多步骤,比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发以及响应请求等步骤。限于篇幅原因,本篇文章无法对所有的步骤一一进行分析。本篇文章将会重点分析请求的发送与接收、编解码、线程派发以及响应的发..._dubbo 服务调用过程源码解析

MATLAB/Simulink生成DSP代码——环境搭建(前期准备)_matlab转dsp-程序员宅基地

文章浏览阅读1.9k次。MATLAB/Simulink生成DSP代码——环境搭建(前期准备)_matlab转dsp

Linux内核(一) [ IMX RK ] TTY-UART驱动框架解析_内核tty框架-程序员宅基地

文章浏览阅读1.4k次。平台:NXP imx6ull 内核版本:4.1.15文章目录一、Linux TTY驱动框架二、Linux Uart驱动框架三、UART相关结构体uart_driver(UART驱动结构体) 、uart_port(UART端口) 、uart_ops(UART操作函数集)四、设备树配置五、串口驱动分析一、Linux TTY驱动框架Linux TTY驱动程序代码位于/drivers/tty下面。TTY整体框架大致分为TTY应用层、TTY文件层、TTY线路规程层、TTY驱动层、TTY设备驱动层。TTY应_内核tty框架

随便推点

Matlab幅频曲线和滤波器设计_陷波滤波器matlab幅相频曲线-程序员宅基地

文章浏览阅读1w次,点赞7次,收藏28次。前言少叙,下面开始正题。一.离散数字信号的表示n=-3:5;subplot(221);x1=(n==0);stem(n,x1,'.');title('单位冲击');axis([-4,4,-1,2]);grid on;subplot(222);x2=[n>=0];stem(n,x2,'.');title('单位阶跃');axis([-4,4,-1,2]);grid;subplot(2_陷波滤波器matlab幅相频曲线

QQ邮箱SMTP发送邮件时要注意哪些安全设置?-程序员宅基地

文章浏览阅读327次,点赞7次,收藏5次。只有做好这些安全设置,才能确保你的邮件发送过程既顺畅又安全。AokSend,利用API/SMTP接口,轻松对接QQ邮箱SMTP,一键发送邮件,高效便捷,助力企业沟通无障碍,营销宣传更给力!

100000569 - 《算法笔记》2.5小节——C/C++快速入门->数组-程序员宅基地

文章浏览阅读135次。《算法笔记》2.5小节——C/C++快速入门->数组26039 Problem A 习题6-4 有序插入#include <stdio.h>int main() { int a[10]; for (int i = 0; i < 10; i++) { scanf("%d", &a[i]); } int temp = a[9]; int j; f...

ICP算法详解——我见过最清晰的解释-程序员宅基地

文章浏览阅读4.2w次,点赞52次,收藏481次。问题引入 迭代最近点(Iterative Closest Point, 下简称ICP)算法是一种点云匹配算法。 假设我们通过RGB-D相机得到了第一组点云,相机经过位姿变换(旋转加平移)后又拍摄了第二组点云,注意这里的 和 的坐标分别对应移动前和移动后的坐标系(即坐标原点始终为相机光心,这里我们有移动前、移动后两个坐标系),并且我们通过相关算法筛选和调整了点云存储的顺序,使得和中的点一一对应,如在三维空间中对应同一个点。 现在我们要解决的问题..._icp算法

计算机绘图形考检测1-6,江苏开放大学计算机绘图形考1-程序员宅基地

文章浏览阅读343次。《江苏开放大学计算机绘图形考1》由会员分享,可在线阅读,更多相关《江苏开放大学计算机绘图形考1(15页珍藏版)》请在人人文库网上搜索。1、江 苏 开 放 大 学形成性考核作业学 号 姓 名 课程代码 110037课程名称 计算机绘图评阅教师 第 1 次任务共 4 次任务任务内容:一:根据已知条件利用直线命令绘制五角星。(不标注尺寸)结果作答:绘图步骤:步骤一:绘制直线命令: _line 指定第一点..._二:绘制含圆的平面图形(分层设置线型和线宽),不标注尺寸。(其中:左上角和右下角的

物联网pyqt5应用管理系统(Python、华为云)_python 基于pyqt的管理系统-程序员宅基地

文章浏览阅读427次。物联网应用管理系统是基于Python和PyQt5技术栈实现的应用端,旨在提供对烟感设备、水质设备和井盖设备等物联网设备的综合管理功能。该系统实现了设备管理、数据监控和远程控制等功能,并通过华为云平台实现了数据存储和云服务支持。_python 基于pyqt的管理系统

推荐文章

热门文章

相关标签