I have the following code. I'm trying to do a breadth first search of a tree that I created call HabitItem.
Here is queue traveral
import java.io.File;
import java.util.*;
import java.util.concurrent.PriorityBlockingQueue;
public static void traverseQueue() {
queueHabitItems.add(head);
while(!queueHabitItems.isEmpty()){
HabitItem node = queueHabitItems.peek();
for(int i = 0; i < node.children.size(); i++)
{
HabitItem it = node.children.get(i);
System.out.print("node: ");
System.out.print(node.name);
System.out.print(", child: ");
System.out.println(it.name);
queueHabitItems.offer(it);
}
queueHabitItems.poll();
System.out.println("Something Good Is Coming");
}
}
I'm trying to implement a Queue. And I'm using the Poll() function to remove elements. Suppose I have the following Data in the Queue.
A B C D E
And I want to use poll() to remove the front element. Well for some reason, E goes to the front of the list, such that it becomes
E B C D
Am I doing something wrong or is there something that I don't fundamentally understand about Queues? Shouldn't B be the front item?
public class myMain {
static PriorityQueue<HabitItem> queueHabitItems = new PriorityQueue<HabitItem>();
static HabitItem head = new HabitItem("A");
static HabitItem B = new HabitItem("B");
static HabitItem C = new HabitItem("C");
static HabitItem D = new HabitItem("D");
static HabitItem E = new HabitItem("E");
static HabitItem F = new HabitItem("F");
static HabitItem G = new HabitItem("G");
static HabitItem H = new HabitItem("H");
static HabitItem I = new HabitItem("I");
static HabitItem J = new HabitItem("J");
static HabitItem K = new HabitItem("K");
static HabitItem L = new HabitItem("L");
static HabitItem M = new HabitItem("M");
static HabitItem N = new HabitItem("N");
static HabitItem O = new HabitItem("O");
public static void hardCodeHabits() {
System.out.print(D.id);
head.children.add(B);
head.children.add(C);
head.children.add(D);
head.children.add(E);
B.children.add(F);
B.children.add(G);
B.children.add(H);
C.children.add(I);
B.children.add(J);
E.children.add(K);
I.children.add(L);
L.children.add(N);
L.children.add(M);
N.children.add(O);
System.out.print(D.id);
}
public static void traverseQueue() {
queueHabitItems.add(head);
while(!queueHabitItems.isEmpty()){
HabitItem node = queueHabitItems.peek();
for(int i = 0; i < node.children.size(); i++)
{
HabitItem it = node.children.get(i);
System.out.print("node: ");
System.out.print(node.name);
System.out.print(", child: ");
System.out.println(it.name);
queueHabitItems.offer(it);
}
queueHabitItems.remove();
System.out.println("Something Good Is Coming");
}
}
public static void main(String[] args) {
System.out.println("Hello world");
hardCodeHabits();
traverseQueue();
try{
Scanner x = new Scanner(new File("justText.txt"));
Formatter y = new Formatter(new File("output.txt"));
y.format("%s", "hey");
y.close();
while (x.hasNext()) {
System.out.println(x.next());
}
}
catch(Exception e) {
System.out.println("Couldn't open the file!");
}
}
}
This is my HabitItems class
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class HabitItem implements Comparable<HabitItem> {
static int Counter = 0;
String name;
boolean completed[] = new boolean[7];
List<HabitItem> children = new ArrayList<HabitItem>();
int id;
public String getName(){
return name;
}
public boolean[] getCompleted(){
return completed;
}
public void setCompleted(int index, boolean checked){
completed[index] = checked;
}
public boolean isChecked(int index){
return completed[index];
}
public HabitItem(String name) {
super();
Counter++;
this.id = Counter;
this.name = name;
for(int i = 0; i < 7; i++){
completed[i] = false;
}
}
public HabitItem(int id) {
super();
Counter++;
this.id = id;
}
public int compareTo(HabitItem o) {
if(o.id == this.id)
{
return 1;
}
else
{
return 0;
}
}
}
Again, don't use peek, use remove:
while (!queueHabitItems.isEmpty()) {
//!! HabitItem node = queueHabitItems.peek();
HabitItem node = queueHabitItems.remove();
for (int i = 0; i < node.children.size(); i++) {
HabitItem it = node.children.get(i);
System.out.print("node: ");
System.out.print(node.name);
System.out.print(", child: ");
System.out.println(it.name);
queueHabitItems.offer(it);
}
// !! queueHabitItems.remove();
System.out.println("Something Good Is Coming");
}
The peek call just peeks into the collection but does not respect the priority. The poll and remove do respect this.
This is very old and probably doesn't matter anymore. But I will just say that it turned out that I was confused because I thought a priorityQueue was the exact same thing as a queue.
Related
I am tasked with creating a Java BFS Algorithm without using the built-in LinkedList and Dynamic ArrayList.
I managed to find 2 examples that seem to achieve the result that I am looking for. They can be found below. When I compare my results to the examples I have found my results seem to have duplicated links.
I suspect it has something to do with my contains() method however having tried many different options that I found from Java: Implement String method contains() without built-in method contains() the issue still persist.
Could someone pls help me with this? Thank you so much in advance!!
Examples
https://github.com/theexplorist/WebCrawler
https://www.youtube.com/watch?v=lyVjfz2Tuck&ab_channel=SylvainSaurel (The code in the video can be found below)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WebCrawler {
public static Queue<String> queue = new LinkedList<>();
public static Set<String> marked = new HashSet<>();
public static String regex = "http[s]*://(\\w+\\.)*(\\w+)";
public static void bfsAlgorithm(String root) throws IOException{
queue.add(root);
BufferedReader br = null;
while (!queue.isEmpty()){
String crawledUrl = queue.poll();
System.out.println("\n=== Site crawled : " + crawledUrl + " ===");
if(marked.size() > 100)
return;
boolean ok = false;
URL url = null;
while(!ok){
try{
url = new URL(crawledUrl);
br = new BufferedReader(new InputStreamReader(url.openStream()));
ok = true;
} catch (MalformedURLException e) {
System.out.println("*** Maformed URL : " + crawledUrl);
crawledUrl = queue.poll();
ok = false;
}
}
StringBuilder sb = new StringBuilder();
String tmp = null;
while((tmp = br.readLine()) != null){
sb.append(tmp);
}
tmp = sb.toString();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(tmp);
while (matcher.find()){
String w = matcher.group();
if(!marked.contains(w)){
marked.add(w);
System.out.println("Sited added for crawling : " + w);
queue.add(w);
}
}
}
if(br != null){
br.close();
}
}
public static void showResults(){
System.out.println("\n\nResults : ");
System.out.println("Web sites crawled : " + marked.size() + "\n");
for (String s: marked){
System.out.println("* " + s);
}
}
public static void main(String[] args){
try{
bfsAlgorithm("https://www.tesla.com/");
showResults();
} catch (IOException e) {
}
}
}
Below are the results for the root url: https://en.wikipedia.org/
I edited the code to only show the first 20 links.
Result from https://github.com/theexplorist/WebCrawler
Result from the Youtube Video
Result from my code
If you look at my result you will see that there are duplicated links.
Pls find my code below
Main.java
public static void main(String[] args) {
WebCrawler crawler = new WebCrawler();
String rootUrl = "https://en.wikipedia.org/";
crawler.discoverWeb(rootUrl);
}
}
DA.java (Dynamic Array)
class DA{
int size;
int capacity = 10;
Object[] nameofda;
public DA(){
this.nameofda = new Object[capacity];
}
public DA(int capacity){
this.capacity = capacity;
this.nameofda = new Object[capacity];
}
public void add(Object anything){
if(size >= capacity){
grow();
}
nameofda[size] = anything;
size++;
}
public void insert(int index, Object anything){
if(size >= capacity){
grow();
}
for (int i = size; i > index; i--){
nameofda[i] = nameofda[i - 1];
}
nameofda[index] = anything;
size++;
}
public void delete(Object anything){
for(int i = 0; i < size; i++){
if(nameofda[i] == anything){
for(int j = 0; j < (size - i - 1); j++){
nameofda[i + j] = nameofda[i + j + 1];
}
nameofda[size - 1] = null;
size--;
if(size <=(int)(capacity/3)){
shrink();
}
break;
}
}
}
public boolean contains(Object anything){
for(int i = 0; i < size; i++){
if (nameofda[i] == anything){
return true;
}
}
return false;
}
private void grow(){
int newcap = (int)(capacity *2);
Object[] newnameofda = new Object[newcap];
for(int i = 0; i < size; i++){
newnameofda[i] = nameofda[i];
}
capacity = newcap;
nameofda = newnameofda;
}
private void shrink(){
int newcap = (int)(capacity / 2);
Object[] newnameofda = new Object[newcap];
for(int i = 0; i < size; i++){
newnameofda[i] = nameofda[i];
}
capacity = newcap;
nameofda = newnameofda;
}
public boolean isEmpty(){
return size == 0;
}
public String toString(){
String nameofstring = "";
for(int i = 0; i < size; i++){
nameofstring += nameofda[i] + ", ";
}
if(nameofstring != ""){
nameofstring = "[" + nameofstring.substring(0, nameofstring.length() - 2) + "]";
}
else {
nameofstring = "[]";
}
return nameofstring;
}
Queue.java (LinkedList)
public class Queue<T> {
private Node<T> front;
private Node<T> rear;
private int length;
private static class Node<T> {
private final T data;
private Node<T> next;
public Node(T data) {
this.data = data;
}
}
public void enQueue(T item) {
if (front == null) {
rear = new Node<T>(item);
front = rear;
} else {
rear.next = new Node<T>(item);
rear = rear.next;
}
length++;
}
public T deQueue() {
if (front != null) {
T item = front.data;
front = front.next;
length--;
return item;
}
return null;
}
public int size() {
return length;
}
public boolean isEmpty(){
return length == 0;
}
public void displayQueue() {
Node<T> currentNode = front;
while (currentNode != null) {
System.out.print(currentNode.data+" ");
currentNode = currentNode.next;
}
}
}
WebCrawler.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WebCrawler {
private Queue<String> queue;
DA discoveredWebsitesList = new DA(5);
public WebCrawler() {
this.queue = new Queue<>();
}
public void discoverWeb(String root) {
this.queue.enQueue(root);
this.discoveredWebsitesList.add(root);
while (!queue.isEmpty()) {
String v = this.queue.deQueue();
StringBuilder rawHtml = readUrl(v);
String regexe = "https://(\\w+\\.)*(\\w+)";
Pattern pattern = Pattern.compile(regexe);
Matcher matcher = pattern.matcher(rawHtml);
while(matcher.find()){
String actualUrl = matcher.group();
if(!this.discoveredWebsitesList.contains(actualUrl)){
this.discoveredWebsitesList.add(actualUrl);
System.out.println("website has been found with URL :" + actualUrl);
this.queue.enQueue(actualUrl);
//System.out.println("Size is: " + queue.size());
if(queue.size() == 20){
System.exit(0);
}
}
}
}
}
public StringBuilder readUrl(String v) {
StringBuilder rawHtml = new StringBuilder() ;
URL ur;
try {
ur = new URL(v);
BufferedReader br = new BufferedReader(new InputStreamReader(ur.openStream()));
String inputLine = "";
while((inputLine = br.readLine()) != null){
rawHtml.append(inputLine);
}br.close();
} catch (Exception e) {
e.printStackTrace();
}
return rawHtml;
}
}
i have to code the Dijkstra algorithm. We got a blueprint for this project. Meaning we were told the classes, field variables and methods we have to use.
We have to read the adjacency matrix from a csv file and then use the Dijkstra algorithm.
My problem already begins in in filling the TreeSet edges...
The problem occurs in Graph.class on line 45 when i try to add the Edges.
Example for the csv :
;A;B;C;D;E;F;G;H
A;;1;3;1;;;;
B;1;;;;3;3;;
C;3;;;1;;;1;
D;1;;1;;1;;2;
E;;3;;1;;1;;5
F;;3;;;1;;;1
G;;;1;2;;;;1
H;;;;;5;1;1;
=>
A -> (B,1), (C,3), (D,1)
B -> (A,1), (E,3), (F,3)
C -> (A,3), (D,1), (G,1)
D -> (A,1), (C,1), (E,1), (G,2)
E -> (B,3), (D,1), (F,1), (H,5)
F -> (B,3), (E,1), (H,1)
G -> (C,1), (D,2), (H,1)
H -> (E,5), (F,1), (G,1)
Could somebody look where my problem is ? My indices are correct i checked them with some sout.
Just need help with filling in the TreeSet! I want to try the Dijkstra part myself.
public class Edge implements Comparable<Edge>{
private int distance;
private Node neighbour;
public Edge(int distance, Node neighbour) {
this.distance = distance;
this.neighbour = neighbour;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public Node getNeighbour() {
return neighbour;
}
public void setNeighbour(Node neighbour) {
this.neighbour = neighbour;
}
#Override
public int compareTo(Edge o) {
if (this.neighbour.getId().equals(o.neighbour.getId())){
return 0;
}else{
return -1;
}
}
}
import java.util.TreeSet;
public class Node {
private String id;
private TreeSet<Edge> edges;
private int distance;
private Node previous;
private boolean isVisited;
public Node(String id) {
this.id = id;
this.edges = new TreeSet<>();
}
public Node(String id, int distance){
this.id = id;
this.distance = distance;
}
#Override
public String toString() {
return "Node{" +
"id='" + id + '\'' +
", edges=" + edges +
", distance=" + distance +
", previous=" + previous +
", isVisited=" + isVisited +
'}';
}
public String getPath(){
return null;
}
public void addEdge(Edge e){
edges.add(e);
}
public void init(){
}
public void setStartNode(Node n){
}
public void visit(Node n){
}
public String getId() {
return id;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.util.*;
public class Graph {
private PriorityQueue pq;
private ArrayList<Node> nodes;
public Graph(){
this.pq = new PriorityQueue();
this.nodes = new ArrayList();
}
public void readGraphFromAdjacencyMatrixFile(Path file) throws FileNotFoundException {
Scanner sc = new Scanner(new File(String.valueOf(file)));
ArrayList<String> s = new ArrayList<>();
ArrayList<Character> nodesCharacter = new ArrayList<Character>();
while (sc.hasNext()){
s.add(sc.next());
}
sc.close();
for(char ch: s.get(0).toCharArray()){
if (ch != ';' && ch != ',') {
nodes.add(new Node(Character.toString(ch)));
nodesCharacter.add(ch);
}
}
ArrayList<Node> nodes2 = getNodes();
String node = "";
int index = 0;
for (int i = 1; i < s.size(); i++){
int cnt = -2;
char[] chArray = s.get(i).toCharArray();
for (int j = 0; j < chArray.length; j++){
if(j == 0){
node = String.valueOf(chArray[j]);
index = indexOfNode(String.valueOf((chArray[j])));
}
else if (j >= 2){
if (Character.isDigit(chArray[j])){
int neighbourIndex = indexOfNode("" + nodesCharacter.get(cnt));
Edge e = new Edge(Character.getNumericValue(chArray[j]), nodes.get(neighbourIndex));
nodes.get(index).addEdge(e);
cnt--;
}
}
cnt ++;
}
}
}
public String getAllPAths(){
return null;
}
public void calcWithDijkstra(String startNodeId){
}
public ArrayList<Node> getNodes() {
return nodes;
}
public int indexOfNode(String id){
int cnt = 0;
for (int i = 0; i < nodes.size(); i++){
if (id.equals(nodes.get(i).getId())){
return cnt;
}
cnt++;
}
return -1;
}
}
I have a graph that contains objects of type GraphNodes. These nodes contain an object City that has properties if It's infected or not. I want to loop through all the nodes and check if a city is infected or not. I have a generic method getInfo which returns an object of type E in my case City. But when i try to chain another method or to get property i can't see them as if they are not available. All the classes in the code are from college so i can't add/remove methods. I've tried with foreach but I still can't get the methods.
Code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.LinkedList;
class City {
String osnovna_granka;
boolean zarazen;
City(String osnovna_granka, boolean zarazen) {
this.osnovna_granka = osnovna_granka;
this.zarazen = zarazen;
}
#Override
public String toString() {
if (zarazen == true) {
return osnovna_granka + " zarazen";
} else {
return osnovna_granka + " nezarazen";
}
}
}
class Graph {
int num_nodes;
GraphNode<City> adjList[];
#SuppressWarnings("unchecked")
public Graph(int num_nodes) {
this.num_nodes = num_nodes;
adjList = (GraphNode<City>[]) new GraphNode[num_nodes];
}
int adjacent(int x, int y) {
// proveruva dali ima vrska od jazelot so
// indeks x do jazelot so indeks y
return (adjList[x].containsNeighbor(adjList[y])) ? 1 : 0;
}
void addEdge(int x, int y) {
// dodava vrska od jazelot so indeks x do jazelot so indeks y
if (!adjList[x].containsNeighbor(adjList[y])) {
adjList[x].addNeighbor(adjList[y]);
}
}
void deleteEdge(int x, int y) {
adjList[x].removeNeighbor(adjList[y]);
}
#Override
public String toString() {
String ret = new String();
for (int i = 0; i < this.num_nodes; i++) {
ret += i + ": " + adjList[i] + "\n";
}
return ret;
}
}
class GraphNode<E> {
private int index;//index (reden broj) na temeto vo grafot
private E info;
private LinkedList<GraphNode<E>> neighbors;
public GraphNode(int index, E info) {
this.index = index;
this.info = info;
neighbors = new LinkedList<GraphNode<E>>();
}
boolean containsNeighbor(GraphNode<E> o) {
return neighbors.contains(o);
}
void addNeighbor(GraphNode<E> o) {
neighbors.add(o);
}
void removeNeighbor(GraphNode<E> o) {
if (neighbors.contains(o)) {
neighbors.remove(o);
}
}
#Override
public String toString() {
String ret = "INFO:" + info + " SOSEDI:";
for (int i = 0; i < neighbors.size(); i++) {
ret += neighbors.get(i).info + " ";
}
return ret;
}
#Override
public boolean equals(Object obj) {
#SuppressWarnings("unchecked")
GraphNode<E> pom = (GraphNode<E>) obj;
return (pom.info.equals(this.info));
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public E getInfo() {
return info;
}
public void setInfo(E info) {
this.info = info;
}
public LinkedList<GraphNode<E>> getNeighbors() {
return neighbors;
}
public void setNeighbors(LinkedList<GraphNode<E>> neighbors) {
this.neighbors = neighbors;
}
}
public class Main {
public static void main(String[] args) throws Exception {
int i, j, k;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
Graph g = new Graph(N);
for (i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
st.nextToken();
String osnovna_granka = st.nextToken();
String str_zarazen = st.nextToken();
if (str_zarazen.equals("zarazen")) {
g.adjList[i] = new GraphNode(i, new City(osnovna_granka, true));
} else {
g.adjList[i] = new GraphNode(i, new City(osnovna_granka, false));
}
}
int M = Integer.parseInt(br.readLine());
for (i = 0; i < M; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
g.addEdge(a, b);
g.addEdge(b, a);
}
br.close();
Stack<GraphNode> stack = new Stack<>();
int counter = 0;
// vasiot kod ovde;
for(GraphNode gn: g.adjList) {
gn.getInfo().// Here the properties of City should show up
}
}
}
GraphNode is a generic type and you have not specified the type, the IDE cannot infer the type so no methods can be suggested. in the for loop you need to specify the type of the GraphNode.
for(GraphNode<City> gn: g.adjList)
I have written a class for the undirected graphs and a symbol table to convert edges from strings to numbers and vise versa but the two string method is not working as i get a stack overflow error. i have implemented a LinkedStack which is the same as a stack in java's library. I am not getting a compilation error and I would appreciate it if could look at the toString method. the other methods are working fine. here is the code below. I think the problem is when i call the iterator
public class EdgeWeightedGraph {
private final int V;
private int E;
private LinkedStack<Edge>[] adj;
public EdgeWeightedGraph(int V){
this.V = V;
this.E = 0;
adj = new LinkedStack[V];
for (int v = 0; v < V; v++)
{
adj[v] = new LinkedStack<Edge>();
}
}
public int V(){
return V(); // This was the error. thank you for spotting it :)
}
public int E(){
return E;
}
public int degree(int v){
return adj[v].size();
}
public void addEdge(Edge e){
int v = e.either();
int w = e.other(v);
adj[v].push(e);
adj[w].push(e);
E++;
}
public Iterable<Edge> adj(int v){
return adj[v];
}
public Iterable<Edge> edges(){
LinkedStack<Edge> b = new LinkedStack<Edge>();
for(int v = 0; v < V; v++)
{
for(Edge e: adj[v])
{
if(e.other(v) > v)
b.push(e);
}
}
return b;
}
}
as for the othe class which contains the toString()
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class EdgeSymbolGraph {
private ST<String, Integer> st;
private String[] keys;
private EdgeWeightedGraph G;
public EdgeSymbolGraph(File stream){
st = new ST<String, Integer>();
try
{
Scanner in = new Scanner(stream);
while(in.hasNextLine())
{
String v1 = in.next();
String v2 = in.next();
if(!st.contains(v1))
st.put(v1, st.size());
if(!st.contains(v2))
st.put(v2, st.size());
}
keys = new String[st.size()];
for(String name: st.keys())
keys[st.get(name)] = name;
G = new EdgeWeightedGraph(st.size());
Scanner m = new Scanner(stream);
for(int i = 0; m.hasNextLine(); i++)
{
int v1 = st.get(m.next());
int v2 = st.get(m.next());
Edge e = new Edge(v1, v2, i);
G.addEdge(e);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
public EdgeWeightedGraph getGraph(){
return G;
}
public String name(int v){
return keys[v];
}
public int index(String s){
return st.get(s);
}
public String toString(){ //this the method that needs fixing
StringBuilder s = new StringBuilder();
s.append(G.V() + " " + G.E() + "\n");
for (int v = 0; v < G.V(); v++)
{
s.append(name(v) + " : ");
for (Edge e: G.adj(v)) // I think this is the problem when i call iterator
{
s.append(e.toString() + " ");
}
s.append("\n");
}
return s.toString();
}
}
Your definition of the method V() is recursive and probably is going into an infinite loop. You probably want it to be:
public int V(){
return V;
}
I have a problem in my Java code that should simulate dining pholosophers problem, which is described here: http://en.wikipedia.org/wiki/Dining_philosophers_problem
I want to output the current state of all philosophers every time one of them eats or thinks. Output should look something like this:
"O X O o X (2)", where "X" means that philosopher eats, "O" means that he is thinking, and "o" means that he is waiting for chopsticks. The number in brackets indicates the number of the philosopher whose state has changed. The problem that I have is that only philosophers 1 and 3 (sometimes 2 and 4) eat, while others always think or wait for forks, and that repeats constantly, so the output looks like this:
O X O O O (2)
o X o X O (4)
o O o X o (2)
o O o O o (4)
o X o O o (2)
o X o X o (4)
o O o X o (2)
...
Complete code is here:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Stick{
boolean available;
public Stick(){
available = true;
}
public void setAvailability(boolean flag){
this.available = flag;
}
public boolean getAvailability(){
return available;
}
}
class Philosopher extends Thread{
private int id;
private Stick l, r;
private Lock monitor;
private Condition[] cond;
private Problem p;
private void outputState(int _id){
StringBuffer sb = new StringBuffer();
for(int i=0; i<5; i++)
sb.append(p.getState(i) + " ");
System.out.println(sb + "(" + (_id+1) + ")");
}
private void takeChopSticks(int _id) throws InterruptedException{
monitor.lock();
try{
p.setState(_id, "o");
while(!l.getAvailability() || !r.getAvailability()){
cond[_id].await();
}
l.setAvailability(false);
r.setAvailability(false);
p.setState(_id, "X");
outputState(_id);
}finally{
monitor.unlock();
}
}
private void eat() throws InterruptedException{
Thread.sleep(1000);
}
private void think(int _id) throws InterruptedException{
Thread.sleep(2000);
}
public void run(){
while(true){
try{
takeChopSticks(this.id);
eat();
releaseChopSticks(this.id);
think(this.id);
}catch(InterruptedException e){System.out.println("srusila se metoda run()");}
}
}
private void releaseChopSticks(int _id) throws InterruptedException{
monitor.lock();
try{
l.setAvailability(true);
r.setAvailability(true);
cond[_id].signalAll();
cond[(_id+4)%5].signalAll();
p.setState(_id, "O");
outputState(_id);
}finally{
monitor.unlock();
}
}
public Philosopher(Problem _p, int _id, Stick _l, Stick _r, Lock m){
cond = new Condition[5];
monitor = m;
id = _id;
l = _l;
r = _r;
p = _p;
for(int i=0; i<5; i++)
cond[i] = monitor.newCondition();
}
}
public class Problem {
Thread[] t;
Stick[] s;
private enum State {O, X, o};
private State[] state;
public State getState(int id){
return state[id];
}
public void setState(int id, String s){
if(s == "o")
state[id] = State.o;
else if(s=="O")
state[id] = State.O;
else if(s=="X")
state[id] = State.X;
}
public Problem(){
state = new State[5];
t = new Thread[5];
s = new Stick[5];
for(int i=0; i<5; i++){
s[i] = new Stick();
state[i] = State.O;
}
Lock m = new ReentrantLock();
for(int i=0; i<5; i++)
t[i] = new Philosopher(this, i, s[i], s[(i+4)%5], m);
for(int i=0; i<5; i++)
t[i].start();
}
public static void main(String[] args){
new Problem();
}
}
I know there are allready several questions about dining philosophers in Java, but none of them seem to help, and my code is a bit different. Thanks.
I've modified it quite a bit and it finally works.
The code is:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Chopstick{
private boolean availability;
public Chopstick(){
availability = true;
}
public boolean getAvailability(){
return availability;
}
public void setAvailability(boolean flag){
availability = flag;
}
}
class Helper{
private Lock mutex = null;
private Condition[] cond;
private String[] state;
private int[] id;
private void outputState(int id){
StringBuffer line = new StringBuffer();
for(int i=0; i<5; i++)
line.append(state[i] + " ");
System.out.println(line + "(" + (id+1) + ")");
}
public Helper(){
id = new int[5];
mutex = new ReentrantLock();
state = new String[5];
cond = new Condition[5];
for(int i=0; i<5; i++){
id[i] = i;
state[i] = "O";
cond[i] = mutex.newCondition();
}
}
public void setState(int id, String s){
state[id] = s;
}
public void grabChopsticks(int id, Chopstick l, Chopstick r){
mutex.lock();
try{
setState(id, "o");
while(!l.getAvailability() || !r.getAvailability())
cond[id].await();
l.setAvailability(false);
r.setAvailability(false);
setState(id, "X");
outputState(id);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
mutex.unlock();
}
}
public void releaseChopsticks(int id, Chopstick l, Chopstick r){
mutex.lock();
try{
setState(id, "O");
l.setAvailability(true);
r.setAvailability(true);
cond[(id+1)%5].signalAll();
cond[(id+4)%5].signalAll();
outputState(id);
}finally{
mutex.unlock();
}
}
}
class Philosopher implements Runnable{
private Helper hlp;
private Chopstick l, r;
private int id;
public Philosopher(int id, Chopstick l, Chopstick r, Helper i){
this.hlp = i;
this.l = l;
this.r = r;
this.id = id;
}
private void eat(){
try{
Thread.sleep(2000);
}catch(InterruptedException e){}
}
private void think(){
try{
Thread.sleep(2000);
}catch(InterruptedException e){}
}
public void run(){
while(true){
hlp.grabChopsticks(id, l, r);
eat();
hlp.releaseChopsticks(id, l, r);
think();
}
}
}
public class Problem {
private Chopstick[] s;
private Philosopher[] f;
private Helper hlp;
private void init(){
s = new Chopstick[5];
f = new Philosopher[5];
hlp = new Helper();
for(int i=0; i<5; i++)
s[i] = new Chopstick();
for(int i=0; i<5; i++){
f[i] = new Philosopher(i, s[i], s[(i+4)%5], hlp);
new Thread(f[i]).start();
}
}
public Problem(){
init();
}
public static void main(String[] args){
new Problem();
}
}