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结果,因为每个时刻最多能够满足两个人同时进餐,且两人座位不相邻。

时间: 2024-10-12 16:58:39

Java多线程,哲学家就餐问题的相关文章

JAVA并发,经典死锁案例-哲学家就餐

转自:http://blog.csdn.net/tayanxunhua/article/details/38691005 死锁经典案例:哲学家就餐. 这个案例会导致死锁. 通过修改<Java编程思想4>一书中的案例,来做实验,代码更易理解,结果也相对容易控制. 附代码: 筷子类: 1 package com.tyxh.ch21.c6; 2 3 public class Chopstick { 4 private boolean taken = false;//判断是此筷子是否被拿起 5 pub

java多线程总结(二)

线程一般有6个状态: 新建状态:NEW 可运行状态:RUNNABLE 休眠状态:TIMED_WAITING 等待状态:WAITING 阻塞状态:BLOCKED 终止状态"TERMINATED 当我们使用new创建线程之后,线程处于新建状态,当调用start方法之后,线程出于可运行状态,当线程需要获得对象的内置锁,而这个锁被其他线程所占用的时候,线程就出于阻塞状态,当线程等待其他线程通知调度表可以运行时,线程处于等待状态,当一个含有时间参数的方法,必须sleep()方法,可以让线程处于计时等待状态

50个Java多线程面试题

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者精通多线程技术并且有丰富的 Java 程序开发.调试.优化经验,所以线程相关的问题在面试中经常会被提到. 在典型的 Java 面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程, 如何创建线程,用什么方式创建线程比较好(比如:继承 thread 类还是调用 Runnable 接口),

Java多线程面试15道

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题.在投资银行业务中多线程和并发是一个非常受欢迎的话题,特别是电子交易发展方面相关的.他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者有足够的Java线程与并发方面的知识,因为候选人中有很多只浮于表面.用于直接面向市场交易的高容量和低延时的电子交易系统在本质上是并发的.下面这些是我在不同时间不同地点喜欢问的Jav

java 多线程面试题

0.Java中多线程同步是什么? 在多线程程序下,同步能控制对共享资源的访问.如果没有同步,当一个Java线程在修改一个共享变量时,另外一个线程正在使用或者更新同一个变量,这样容易导致程序出现错误的结果. 1.解释实现多线程的几种方法? Java线程可以实现Runnable接口或者继承Thread类来实现,当你打算多重继承时,优先选择实现Runnable.还可以使用线程池. 2.Thread.start()与Thread.run()有什么区别? Thread.start()方法(native)启

Thking in Java---从哲学家就餐问题看死锁现象

我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任务在等待另一个任务,而后者又在等待其它任务,这样一直下去,知道这个链条下的任务又在等待第一个任务释放锁,这样就形成了一个任务之间相互等待的连续循环,没有任务可以继续的情况.死锁的最大问题在于它发生的几率非常小,并不是我们一运行程序它就死锁了,而是会不知道那个时候程序就死锁了并且我们很难重现当时出现死

java多线程基本概述(四)——死锁

package mytask; public class Task { public static void main(String[] args) { DeadThread thread = new DeadThread(); Thread t1 = new Thread(thread); t1.setName("a"); Thread t2 = new Thread(thread); t2.setName("b"); t1.start(); t2.start()

15个顶级Java多线程面试题及答案

1)现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉.这个多线程问题比较简单,可以用join方法实现. 2)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像Con

15个顶级Java多线程面试题及回答

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程 的问题.在投资银行业务中多线程和并发是一个非常受欢迎的话题,特别是电子交易发展方面相关的.他们会问面试者很多令人混淆的Java线程问题.面试官只 是想确信面试者有足够的Java线程与并发方面的知识,因为候选人中有很多只浮于表面.用于直接面向市场交易的高容量和低延时的电子交易系统在本质上是并 发的.下面这些是我在不同时间不同地点喜欢问的

15个java多线程面试题及回答

1)现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉.这个多线程问题比较简单,可以用join方法实现. 2)在Java中Lock接口比synchronized块的优势是什么? 你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像Co