哲学家就餐问题中的JAVA多线程学习_java

问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。

解决办法:

1、添加一个服务生,只有当经过服务生同意之后才能拿筷子,服务生负责避免死锁发生。

2、每个哲学家必须确定自己左右手的筷子都可用的时候,才能同时拿起两只筷子进餐,吃完之后同时放下两只筷子。

3、规定每个哲学家拿筷子时必须拿序号小的那只,这样最后一位未拿到筷子的哲学家只剩下序号大的那只筷子,不能拿起,剩下的这只筷子就可以被其他哲学家使用,避免了死锁。这种情况不能很好的利用资源。 

代码实现:实现第2种方案

复制代码 代码如下:

package cn.edu.sdust.Philosopher;

/*每个哲学家相当于一个线程*/
class Philosopher extends Thread{
    private String name;
    private Fork fork;
    public Philosopher(String name,Fork fork){
        super(name);
        this.name=name;
        this.fork=fork;
    }

    public void run(){
        while(true){
            thinking();
            fork.takeFork();
            eating();
            fork.putFork();
        }

    }

   
    public void eating(){
        System.out.println("I am Eating:"+name);
        try {
            sleep(1000);//模拟吃饭,占用一段时间资源
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

   
    public void thinking(){
        System.out.println("I am Thinking:"+name);
        try {
            sleep(1000);//模拟思考
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class Fork{
    /*5只筷子,初始为都未被用*/
    private boolean[] used={false,false,false,false,false,false};

    /*只有当左右手的筷子都未被使用时,才允许获取筷子,且必须同时获取左右手筷子*/
    public synchronized void takeFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);
        while(used[i]||used[(i+1)%5]){
            try {
                wait();//如果左右手有一只正被使用,等待
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        used[i ]= true;
        used[(i+1)%5]=true;
    }

    /*必须同时释放左右手的筷子*/
    public synchronized void putFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);

        used[i ]= false;
        used[(i+1)%5]=false;
        notifyAll();//唤醒其他线程
    }
}

//测试
public class ThreadTest {

    public static void main(String []args){
        Fork fork = new Fork();
        new Philosopher("0",fork).start();
        new Philosopher("1",fork).start();
        new Philosopher("2",fork).start();
        new Philosopher("3",fork).start();
        new Philosopher("4",fork).start();
    }
}

运行结果:

复制代码 代码如下:

I am Thinking:0
I am Thinking:2
I am Thinking:3
I am Thinking:1
I am Thinking:4
I am Eating:0
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2
I am Eating:1
I am Thinking:4
I am Eating:3
I am Thinking:1
I am Eating:0
I am Thinking:3
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2

分析:上述解决方案解决了死锁问题。可以看到最多只能有两条相邻的eating结果,因为每个时刻最多能够满足两个人同时进餐,且两人座位不相邻。

时间: 2025-01-30 13:16:12

哲学家就餐问题中的JAVA多线程学习_java的相关文章

Java多线程学习(吐血超详细总结)

  本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等.在这之前,首先让我们来了解下在操作系统中进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.(线程是cpu调度的最小单位) 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止. 多

Java 多线程学习详细总结_java

目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递      本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个

java多线程学习之线程同步

基本上感觉自己学习的东西都是学会了立马就用,很少有机会能专门花时间去学习一些东西,近些时候不忙,准备把公司的面试题全做一遍,难的倒是不多,但是很多人都不会做,问题就是出在实践上. 言归正传.多线程就目前而言,纯是兴趣上的学习,并没有真实的应用场景.以前觉java多线程很乱,很多概念没似懂非懂,但是实战中写几个实例就一目了然了. 昨天练习线程安全时提到了synchronized关键字,其作用原理其实就是把一个或者一部份资源锁住,只允许当前这个进程使用.我理解线程同步就让各个线程之间能够控制资源的分

java基本教程之多线程基本概念 java多线程教程 _java

多线程是Java中不可避免的一个重要主体.下面我们将展开对多线程的学习.接下来的内容,是对"JDK中新增JUC包"之前的Java多线程内容的讲解,涉及到的内容包括,Object类中的wait(), notify()等接口:Thread类中的接口:synchronized关键字. 注:JUC包是指,Java.util.concurrent包,它是由Java大师Doug Lea完成并在JDK1.5版本添加到Java中的. 在进入后面章节的学习之前,先对了解一些多线程的相关概念.线程状态图

Java多线程实例_java

在上篇文章给大家介绍了java多线程的实现方式,通过本文给大家介绍java多线程实例,对java多线程感兴趣的朋友一起学习吧 首先给大家说下多线程的优缺点 多线程的优点: 1)资源利用率更好 2)程序设计在某些情况下更简单 3)程序响应更快 多线程的代价: 1)设计更复杂 虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂.在多线程访问共享数据的时候,这部分代码需要特别的注意.线程之间的交互往往非常复杂.不正确的线程同步产生的错误非常难以被发现,并且重现以修复. 2)上下文切

java多线程学习笔记之线程安全

假设i为银行的存款数据,i = 100, 现在使用A B两个线程(两个人)同时执行 i = i + 10;(存10块钱)的操作,由于默认情况下异步执行,那么流程可能会是这样: 1. A线程从系统内存中读到 i. 2. B线程从系统内存中读到 i. 3. A线程执行 i+10. 4. B线程执行 i+10. 5. A线程将110写回到系统内存,内存中i的值为 110. 6. B线程将110写回到系统内存,内存中i的值为 110,. 显然这程结果是不正确的,少了一个人存的钱. synchronize

java多线程学习初步

import java.io.*; //多线程编程 public class MultiThread { public static void main(String args[]) { System.out.println("我是主线程!"); //下面创建线程实例thread1 ThreadUseExtends thread1=new ThreadUseExtends(); //创建thread2时以实现了Runnable接口的THhreadUseRunnable类实例为参数 Th

java基本教程之Thread中start()和run()的区别 java多线程教程_java

Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start() 和 run()相关源码(基于JDK1.7.0_40) start() 和 run()的区别说明start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用.run()   : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在

java基本教程之synchronized关键字 java多线程教程_java

本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchronized代码块4. 实例锁 和 全局锁 1. synchronized原理 在java中,每一个对象有且仅有一个同步锁.这也意味着,同步锁是依赖于对象而存在.当我们调用某对象的synchronized方法时,就获取了该对象的同步锁.例如,synchronized(obj)就获取了"obj这个对象&quo