代码改变世界

哲学家就餐的问题--java实现

2011-09-15 20:32  Rollen Holt  阅读(8045)  评论(0编辑  收藏  举报

先来看看运行结果吧:

代码分为4个文件:

Chopstick.java

package Philosopher;

/**
 * 表示筷子的类
 * */
public class Chopstick{
	public Chopstick(){

	}

	public Chopstick(int id){
		this.id = id;
	}

	public boolean isAvailable(){
		return available;
	}

	public void setAvailable(boolean available){
		this.available = available;
	}

	public int getId(){
		return id;
	}

	public void setId(int id){
		this.id = id;
	}

	@Override
	public String toString(){
		return "筷子" + id;
	}

	/**
	 * 表示筷子是否可用
	 * */
	private volatile boolean available = true;
	private int id;
}

 ChopstickArray.java

package Philosopher;

public class ChopstickArray{
	public ChopstickArray(){

	}

	public ChopstickArray(int size){
		chopsticks = new Chopstick[size];
		for(int i = 0; i < chopsticks.length; ++i){
			chopsticks[i] = new Chopstick(i);
		}
	}

	public Chopstick getId(int id){
		return chopsticks[id];
	}

	public Chopstick getLast(int id){
		if(id == 0){
			return chopsticks[chopsticks.length - 1];
		}else{
			return chopsticks[id - 1];
		}
	}

	private Chopstick[] chopsticks;
}

DiningPhilosophersFrame.java

package Philosopher;

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class DiningPhilosophersFrame extends JFrame{
	public DiningPhilosophersFrame(){
		panel2.setLayout(new GridLayout(2, 2, 3, 3));
		panel2.add(label2);
		panel2.add(label3);
		panel2.add(label4);
		JScrollPane js1 = new JScrollPane(thinkingTextArea,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		JScrollPane js2 = new JScrollPane(eatingTextArea,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		JScrollPane js3 = new JScrollPane(waitingTextArea,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		panel2.add(js1);
		panel2.add(js2);
		panel2.add(js3);
		panel1.setLayout(new FlowLayout());
		panel1.add(label1);
		panel1.add(panel2);
		panel1.add(button);
		setContentPane(panel1);
		button.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				ChopstickArray chopstickArray = new ChopstickArray(5);
				for(int i = 0; i < 5; i++){
					new Thread(new Philosopher(i, chopstickArray,
							thinkingTextArea, eatingTextArea, waitingTextArea))
							.start();
				}
			}
		});

		setSize(300, 400);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args){
		new DiningPhilosophersFrame();
	}

	private final JPanel panel1 = new JPanel();
	private final JPanel panel2 = new JPanel();

	private final JTextArea thinkingTextArea = new JTextArea(5, 10);
	private final JTextArea eatingTextArea = new JTextArea(5, 10);
	private final JTextArea waitingTextArea = new JTextArea(5, 10);

	JLabel label1 = new JLabel("哲学家问题");
	JLabel label2 = new JLabel("思考");
	JLabel label3 = new JLabel("吃饭");
	JLabel label4 = new JLabel("等待");

	JButton button = new JButton("开始运行");
}

 Philosopher.java

package Philosopher;

import java.util.Random;

import javax.swing.JTextArea;

public class Philosopher implements Runnable{

	public Philosopher(){

	}

	public Philosopher(int id, ChopstickArray chopstickArray,
			JTextArea thinkingTextArea, JTextArea eatingtextArea,
			JTextArea waitingTextArea){
		this.id = id;
		this.chopstickArray = chopstickArray;
		this.thinkingTextArea = thinkingTextArea;
		this.eatingTextArea = eatingtextArea;
		this.waitingTextArea = waitingTextArea;
	}

	public synchronized void thinking(){
		if(state){ // 如果在思考,说明这个哲学家两面的筷子没用
			chopstickArray.getId(id).setAvailable(true);
			chopstickArray.getLast(id).setAvailable(true);
			String text = thinkingTextArea.getText();
			thinkingTextArea.setText(text + this + "在思考\n");
			try{
				Thread.sleep(1000);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		state = false;
	}

	public synchronized void eating(){
		if(!state){ // 在思考
			if(chopstickArray.getId(id).isAvailable()){ // 如果哲学家右手边的筷子可用
				if(chopstickArray.getLast(id).isAvailable()){ // 如果左手边的筷子也可用
					// 然后将这个能吃饭的哲学家两侧的筷子都设置为不可用
					chopstickArray.getId(id).setAvailable(false);
					chopstickArray.getLast(id).setAvailable(false);
					String text = eatingTextArea.getText();
					eatingTextArea.setText(text + this + "在吃饭\n");
					try{
						Thread.sleep(1000);
					}catch(Exception e){
						e.printStackTrace();
					}
				}else{
					// 右手边的筷子可用,但是左手边的不可用
					String str = waitingTextArea.getText();
					waitingTextArea.setText(str + this + "在等待"
							+ chopstickArray.getLast(id) + "\n");
					try{
						wait(new Random().nextInt(100));
					}catch(Exception e){
						e.printStackTrace();
					}
				}
			}else{
				// 如果哲学家右手边的筷子不可用则等待
				String str = waitingTextArea.getText();
				waitingTextArea.setText(str + this + "在等待"
						+ chopstickArray.getId(id) + "\n");
				try{
					wait(new Random().nextInt(100));
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
		state = true;
	}

	@Override
	public void run(){
		for(int i = 0; i < 10; ++i){
			thinking();
			eating();
		}
	}

	@Override
	public String toString(){
		return " 哲学家 " + id;
	}

	private int id;
	private boolean state;
	ChopstickArray chopstickArray;
	JTextArea thinkingTextArea;
	JTextArea eatingTextArea;
	JTextArea waitingTextArea;

}