Java Welcome to Java Class: Learn Java One Bit at a Time

AI Thread Summary
The discussion focuses on learning Java programming step by step, emphasizing the need for a compiler and a runtime environment. The Java compiler converts source code into bytecode, which is executed by a Java Virtual Machine (JVM), allowing Java programs to run on any platform. Participants are guided through the installation of the Java J2SE 1.4.2 SDK and the process of compiling and running a simple Java program. Clarifications are provided on terminology, such as the difference between source code and object code, and the function of convenience files for compiling and running programs. The conversation also addresses troubleshooting issues related to running Java applets and classpath configurations.
  • #51
A good programmer doesn't need a debugger. And no, I'm really not being condescending -- it's true.
Strange statement.

Given some C code that's a couple of thousand lines that compiles fine without any errors at all, yet still gets a segmentation fault at run-time.
What would you do? How would you find that "of by 1" bounds error in some char*? Or that non null-terminated string you are expecting to be null terminated?

Using printf()-statements to check your code is fine, but are you sure you are handling all possible scenarios?

I'd say a debugger is a pretty important and powerfull tool for a programmer.
 
Technology news on Phys.org
  • #52
It's a matter of philosophy, I suppose. I tend to use a variant of cleanroom software engineering techniques, and have not actually written an off-by-one error or an array bounds error in many years. I would actually be quite happy to accept your challenge in regards to a 1kloc piece of code that segfaults. In fact, I would even be willing to bet money on my ability to find the problem in just a few minutes.

I consider off-by-one errors and array bounds errors to be, well... novice mistakes. A debugger can certainly help a new programmer catch these kinds of mistakes, but, as the programmer gains experience, the debugger really just becomes less and less useful.

Once you throw threads and asynchronous data access into things, debuggers really become just about useless. The only way to write zero-defect code is to truly understand the code as you write it, and that takes experience.

- Warren
 
  • #53
A very useful function in c has always been getch() , so that the execution can be stopped at some point and the values can be carefully monitored...
Checking the backtrace is usually a lot faster. You can only guess where the problems are happening, the backtrace tells you where.

I'd say it would be far more superior just using breakpoints in your debugger and checking variables from there. As opposed to opening your file and commenting/uncommenting a debug-line somewhere in your source-code, recompiling and running again.
 
  • #54
I consider off-by-one errors and array bounds errors to be, well... novice mistakes.
They are done by professional programmers all the time. We are only humans.

I'm really not talking about ability here. Very few people will be able to write something huge that just compiles and works perfectly straight away.

It's more about finding the error or how to debug your code.

I'd say a debugger is far superior to any "insert various print-statements in your code" variants.

Once you throw threads and asynchronous data access into things, debuggers really become just about useless
The more complex code, the more complex datastructures etc. the more complex debugging becomes. Using a debugger with threaded code can tell you what thread is causing problems. I don't understand why this would be useless.

I'd actually say it the other way around:
Using a debugger when you are learning programming is dumb. It has only negative effects on your learning experience, but once you get more experienced a debugger is IMO a good thing.
 
  • #55
Dr-NiKoN said:
They are done by professional programmers all the time. We are only humans.
All programmers make mistakes. Few truly professional programmers make the same mistakes that students would make. The type of mistakes a programmer makes is certainly related to his/her experience. The effectiveness of a debugger is related to the type of errors being made, and thus is also related to the programmers experience.
I'm really not talking about ability here. Very few people will be able to write something huge that just compiles and works perfectly straight away.
I never said that. I said that experienced programmers don't make the kind of mistakes that debuggers are good at exposing.
I'd say a debugger is far superior to any "insert various print-statements in your code" variants.
Once again, it's a matter of philosophy. Many experienced programmers, myself included, think quite poorly of overuse of a debugger.
The more complex code, the more complex datastructures etc. the more complex debugging becomes. Using a debugger with threaded code can tell you what thread is causing problems. I don't understand why this would be useless.
What if the problem does not exist in one thread, but exists in the interdependence or cooperation of more than one thread?
Using a debugger when you are learning programming is dumb. It has only negative effects on your learning experience, but once you get more experienced a debugger is IMO a good thing.
You are welcome to your opinion. I have watched many students cling to the debugger far too long. Using a debugger forces a sort of "tunnel vision," in which students will make a change to their code, observe its behavior in the debugger, edit their code again, and so on. They freely add +1, for example, anytime they're off by one, without really considering the larger reason why their loop wasn't initialized properly in the first place. They place bandaids on open wounds without curing the underlying disease.

In my opinion, weaning oneself from a debugger is one of the first steps one can take to really being able to program. Learning strong, systematic software engineering techniques is the second.

- Warren
 
  • #56
Debuggers tend to be a crutch; they make it easier to avoid thinking about the code you are trying to fix, just using trial-and-error instead. Of course, doing trial-and-error programming by inserting prints or logging everywhere isn't any better.

I do agree that a debugger usually isn't harmful to someone who's already a good programmer. But it usually isn't useful, either. Even if you have to fix a really big chunk of spagetti code written by someone else who isn't a good programmer, you're still better off simplifying the code first and then trying to fix it. And debuggers just aren't very useful for simple code.

Debuggers are only useful if you have code that you can't trace through in your head. This generally means that either the code jumps around alot, or has a large number of variables. Both of those things generally only occur in badly written code. Don't write such code yourself. If the code wasn't written by you, make it into good code before you try and debug it. If that is beyond your abilities, then you are not a good programmer.
 
  • #57
My first Java class

Here's my first stab at Java. No fancy graphics, just a simple queue implemented as a linked list. It actually seems to work :approve: but I'd appreciate any constructive criticism you might offer.

In particular, I'm wondering about my implementation of Empty(). In C or C++ I'd never just "dump" the nodes the way I did here, but I get the impression that this is OK in Java. Yes?

Also, should my deQueue() method provide some protection against the user attempting to remove an object from an empty queue, or is the normal practice to leave that for the main program to deal with (as I did here)?

(It's homework, so please offer criticisms/suggestions, but don't rewrite it for me.)

Thanks.


Here's MyQueue.java:
Code:
//	MyQueue.java

public class MyQueue {
	MyNode first;
	MyNode last;
	int size;

	public MyQueue() {
		first = null;
		last = null;
		size = 0;
	}

	public boolean isEmpty() {
		if (size == 0)
			return true;
		else
			return false;
	}

	public void enQueue(Object o) {
		MyNode nextNode = new MyNode(o);
		if (isEmpty()) {
			first = nextNode;
			last = nextNode;
		}
		else {
			last.next = nextNode;
			last = nextNode;
		}
		size++;
	}

	public Object deQueue() {
		MyNode temp = first;
		if (size == 1) {
			first = null;	
			last = null;
			size --;
		}
		else if (size > 1) {
			first = first.next;
			size --;
		}
		return temp.data;
	}

	public void Empty() {
		first = last = null;
		size = 0;
	}
}
			
	


class MyNode {
	Object data;
	MyNode next;

	MyNode (Object o) {
		data = o;
		next = null;
	}

}

and here's a test driver, testMyQueue.java:
Code:
//	testMyQueue.java
//	test driver for MyQueue class

class testMyQueue {
	public static void main(String[] args) {
		MyQueue q = new MyQueue();
		Integer n;

		for(int j=0; j<4; j++) {
			System.out.println("\nTesting five entries to the queue.");
			for(int i=0; i<5; i++) {
				n = new Integer(2*i*j);
				q.enQueue(n);
			}

			while(!q.isEmpty()){
				n = (Integer) q.deQueue();
				System.out.println(n);
			}
		}

		q.Empty();

		if(q.isEmpty()) {
			System.out.println("The queue is now empty.\n");
			System.out.println("One last trial...");
		}

		for(int i=0; i<5; i++) {
			n = new Integer(10*i);
			q.enQueue(n);
		}

		while(!q.isEmpty()){
			n = (Integer) q.deQueue();
			System.out.println(n);
		}


		System.out.println("Goodbye.");
	}
}
 
Last edited:
  • #58
gnome said:
Here's my first stab at Java. No fancy graphics, just a simple queue implemented as a linked list. It actually seems to work :approve: but I'd appreciate any constructive criticism you might offer.

For a first stab it looks pretty good!
No,you don't need to concern yourself with deallocating memory. This is a job for the garbage collector.

A few things:

1. Trying to dequeue an element from an empty queue should throw an exception. This is the usual practice in Java and it is good practice IMO. The client deals with the exception at whatever level it wants.

2. The Java coding convention is to use camel case names for methods (i.e. use "empty" instead of "Empty").

3. Using a sentinel node would simplify a lot of code. For example the empty check becomes "return first == last" and the enque function doesn't need case-by-case analysis. If you don't need a getSize() method then you could discard the size field.

4. The Node class should probably be nested in the Queue class. It can safely be made private. The user shouldn't know or concern himself with such details.

5. The member variables first, last and size should be private.

I hope that helps.

regards,
radu
 
Last edited:
  • #59
Thanks for the suggestions, Radu. I vaguely remember being briefly introduced to sentinels in my Data Structures class a couple of years ago, but I've never used one since then. I have improvised based on what I think a sentinel should do, but I'm not sure it's what you had in mind, unless you're using first as a reference to the sentinel, so please let me know if there's a better (or more generally accepted) way of implementing it.

Regarding the exception class, I haven't found any explanation of the purpose of the line
Code:
super();
Can you shed any light on that?
Also, I see that the "String s" exception constructor is optional, and I can't figure out what purpose it would serve. What can you tell me about that?

Here's my revised code.

MyQueue.java:
Code:
public class MyQueue {
	private class MyNode {
		Object data;
		MyNode next;

		MyNode () {				//	constructor for sentinel node
			data = null;
			next = null;
		}
		MyNode (Object o) {		//	constructor for other nodes
			data = o;
			next = null;
		}
	};

	private MyNode sentinel, last;

	public MyQueue() {
		last = sentinel = new MyNode();
	}

	public boolean isEmpty() {
		return sentinel == last;
	}

	public void enQueue(Object o) {
		MyNode nextNode = new MyNode(o);
		last.next = nextNode;
		last = nextNode;
	}

	public Object deQueue() throws EmptyQueueException {
		if (last == sentinel)
			throw new EmptyQueueException();

		MyNode temp = sentinel.next;
		sentinel.next = temp.next;
		if (last == temp)
			last = sentinel;
		return temp.data;
	}

	public void empty() {
		last = sentinel;
		last.next = null;
	}
}

EmptyQueueException.java:
Code:
public class EmptyQueueException extends java.lang.Exception {
	EmptyQueueException() {
		super();
	}

	EmptyQueueException(String s) {
		super(s);
	}
}


testMyQueue.java
Code:
class testMyQueue {
	public static void main(String[] args) {
		MyQueue q = new MyQueue();
		Integer n;

		for(int j=0; j<4; j++) {
			System.out.println("\nTesting five entries to the queue.");
			for(int i=0; i<5; i++) {
				n = new Integer(2*i*j);
				q.enQueue(n);
			}

			while(true){
				try {
					n = (Integer) q.deQueue();
					System.out.println(n);
				} catch (EmptyQueueException e) {
					System.out.println("Queue is empty");
					break;
				}
			}
		}

		for(int i=0; i<5; i++) {
			n = new Integer(2*i);
			q.enQueue(n);
		}

		q.empty();

		if(q.isEmpty()) {
			System.out.println("The queue is now empty.\n");
			System.out.println("One last trial...");
		}

		for(int i=0; i<5; i++) {
			n = new Integer(10*i);
			q.enQueue(n);
		}

		while(!q.isEmpty()){
			try {
				n = (Integer) q.deQueue();
				System.out.println(n);
			} catch (EmptyQueueException e) {
				System.out.println("We should never get caught here.");
			}
		}

		System.out.println("Goodbye.");
	}
}
 
  • #60
The line "super()" simply invokes the superclass constructor. In this case, it runs the java.lang.Exception constuctor. It is not necessary to explicitly call the superclass constructor, as it will be called automatically anyway, but it's never a bad idea.

The constructor that takes a String argument allows you to provide a message that might be helpful to the user of your class. In this case, the name of the exception is self-explanatory, so the String argument is not very useful. In some cases though, it's nice to provide a bit more detail as to exactly why the exception was thrown.

- Warren
 
  • #61
gnome said:
I have improvised based on what I think a sentinel should do, but I'm not sure it's what you had in mind,

That's what I had in mind :) Here is an article "on sentinels":
http://www.topcoder.com/?&t=features&c=feat_090104

A nice discussion about implementing lists can be found here:
http://tinyurl.com/53tpe
Look especially at lecture notes 4, 5, and 6. If I remember correctly it includes the sentinel stuff.

Code:
	public Object deQueue() throws EmptyQueueException {
		if (last == sentinel)
			throw new EmptyQueueException();

		MyNode temp = sentinel.next;
		sentinel.next = temp.next;
		if (last == temp)
			last = sentinel;
		return temp.data;
	}

You can replace the second if with "sentinel = temp".

regards,
radu
 
  • #62
Originally posted by rgrig
You can replace the second if with "sentinel = temp".
Thanks again. Actually, if I make that change, I can also eliminate the line (sentinel.next = temp.next;) above that second if so now deQueue is just:

Code:
	public Object deQueue() throws EmptyQueueException {
		if (last == sentinel)
			throw new EmptyQueueException();

		MyNode temp = sentinel.next;
		sentinel = temp;
		return temp.data;
	}

Very elegant!

Thanks also to Warren for explaining the exception constructors.
 
  • #63
Unexpected decimal results in java arithmetic

I'm working on a complex number class for homework. What I have so far seems to work correctly, but for some of the results
System.out.print()
gives unexpected decimal representations, such as
5.6i + 2.8i = 8.399999999999999i
yet others are "normal", such as
5.6i - 2.8i = 2.8i

It doesn't seem to be restricted to specific operations; for example when I put different values in the test program, I got
4.0i - 2.8i = 1.2000000000000002i

Is this just a normal consequence of using doubles?

If so, how should I change my
System.out.print()
commands to correct this?

Code:
//	Complex.java
//	implements a complex number type

public class Complex {
	public Complex() {
		_real = 0.0;
		_imag = 0.0;
	}

	public Complex (double re, double im) {
		_real = re;
		_imag = im;
	}

	public static Complex add (Complex x, Complex y) {
		return new Complex(x._real + y._real, x._imag + y._imag);
	}

	public static Complex subt (Complex x, Complex y) {
		return new Complex(x._real - y._real, x._imag - y._imag);
	}

	public static Complex mult (Complex x, Complex y) {
		return new Complex(x._real * y._real, x._imag * y._imag);
	}

	static public Complex div (Complex x, Complex y) {
		return new Complex(x._real / y._real, x._imag / y._imag);
	}

	public static double real(Complex x) {
		return x._real;
	}

	public static double imag(Complex x) {
		return x._imag;
	}

	public double real () {
		return _real;
	}

	public double imag () {
		return _imag;
	}

	private double _real, _imag;
}

with this test driver:
Code:
//	TestComplex.java
//	test driver for Complex class

class TestComplex {

	public static void main (String[] args) {
		double re,im;

		Complex c1, c2, c3, result;
		c1 = new Complex();
		c2 = new Complex();
		c3 = new Complex();
	
		System.out.println("Testing default constructor with instance methods:");
		System.out.println("c1 = " + c1.real() + " + " + c1.imag() + "i");


		System.out.println("Testing default constructor with static methods:");
		System.out.println("c1 = " + Complex.real(c1) + " + " + Complex.imag(c1) + "i");


		System.out.println("Testing set-value constructor:");
		c1 = new Complex(6.4,5.6);
		c2 = new Complex(2.0,2.8);
		System.out.println("c1 = " + c1.real() + " + " + c1.imag() + "i");

		System.out.println("c2 = " + c2.real() + " + " + c2.imag() + "i");


		System.out.println("\nTesting addition:");
		result = Complex.add(c1,c2);
		System.out.print("(" + c1.real() + " + " + c1.imag() + "i)");

		System.out.print(" + (" + c2.real() + " + " + c2.imag() + "i)");

		System.out.println(" = (" + result.real() + " + " + result.imag() + "i)");

		System.out.println("\nTesting subtraction:");
		result = Complex.subt(c1,c2);
		System.out.print("(" +c1.real() + " + " + c1.imag() + "i)");

		System.out.print(" - (" + c2.real() + " + " + c2.imag() + "i)");

		System.out.println(" = (" + result.real() + " + " + result.imag() + "i)");

		System.out.println("\nTesting multiplication:");
		result = Complex.mult(c1,c2);
		System.out.print("(" +c1.real() + " + " + c1.imag() + "i)");

		System.out.print(" * (" + c2.real() + " + " + c2.imag() + "i)");

		System.out.println(" = (" + result.real() + " + " + result.imag() + "i)");

		System.out.println("\nTesting division:");
		result = Complex.div(c1,c2);
		System.out.print("(" +c1.real() + " + " + c1.imag() + "i)");

		System.out.print(" / (" + c2.real() + " + " + c2.imag() + "i)");

		System.out.println(" = (" + result.real() + " + " + result.imag() + "i)");

		System.out.println("\nTesting division by zero:");
		result = Complex.div(c1,c3);
		System.out.print("(" +c1.real() + " + " + c1.imag() + "i)");

		System.out.print(" / (" + c2.real() + " + " + c2.imag() + "i)");

		System.out.println(" = (" + result.real() + " + " + result.imag() + "i)");

		System.out.println("\nFinished.");
	}
}
 
  • #64
Use this:
Code:
NumberFormat numberFormatter = new NumberFormat();
numberFormatter.setMaximumFractionDigits(2);
System.out.println(...numberFormatter.format(c1.real())...);
- Warren
 
  • #65
A Simple Program

Hello.

I have a java program where there is a falling cube. I am trying to make the cube fall, then bounce back up and fall again forever. I know i have to use a for loop.Can someone please guide me as to what to do?


Thanks!
 
  • #66
Does a thread just "go away" when it reaches the end of its run() method, or am I supposed to do something to clean up?
 
  • #67
ghome,

When a Thread's run() method returns, it no longer occupies any CPU resources. It will continue to take up some modest memory resources until there are no more references to it. Then it will be garbage-collected and its memory freed.

- Warren
 
  • #68
Ok, this place is as good as any to post and try and get an answer to this. This program is supposed to read a keyboard input of an integer 1-100 and output the change from a dollar that you get back.

For example: 27

2 Quarters
2 Dimes
3 Pennies

It won't work and I'm killing myself over this. This error comes up when compiling:

java:33: cannot resolve symbol variable Keyboard location: class evan3 amount = Keyboard.readInt ();

Here is the program:

public class evan3
{
public static void main (String[] args)
{

final int DOLLAR = 100;
final int QUARTER = 25;
final int DIME = 10;
final int NICKEL = 5;
final int PENNY = 1;

int amount = 0;
int change = 0;
int numQuarters = 0;
int remQuarters = 0;
int numDimes = 0;
int remDimes = 0;
int numNickels = 0;
int remNickels = 0;
int numPennies = 0;

while (true) // infinite loop
{
System.out.print ("Enter the purchase amount [1-100], enter 0 to exit : ");
amount = Keyboard.readInt ();

if (amount < 0 || amount > 100)
{
System.out.println ("Amount not in range [0 - 100]");
continue;
}

if (amount == 0)
{
System.out.println ("Bye");
break;
}

change = DOLLAR - amount;
numQuarters = change / QUARTER;
remQuarters = change % QUARTER;
numDimes = remQuarters / DIME;
remDimes = remQuarters % DIME;
numNickels = remDimes / NICKEL;
remNickels = remDimes % NICKEL;
numPennies = remNickels / PENNY;


if (numQuarters >1 || numQuarters == 0)
System.out.println ("Quarters");
else
System.out.println ("Quarter");

if (numDimes >1 || numDimes == 0)
System.out.println ("Dimes");
else
System.out.println ("Dime");

if (numNickels >1 || numNickels == 0)
System.out.println ("Nickels");
else
System.out.println ("Quarter");

if (numPennies >1 || numPennies == 0)
System.out.println ("Pennies");
else
System.out.println ("Penny");




} // while

} // main

} // Lab3

Any help? I'm missing something here.
 
  • #69
Well, you're missing that Keyboard class/object you referenced. I have no idea where you heard of a Keyboard class -- perhaps it's something your instructor made up for you to use?

You can always just wrap the System.in stream in a DataInputStream and use its readInt method:

int amount = new DataInputStream(System.in).readInt();

- Warren
 
  • #70
The keyboard class file was something the teacher told us to put in. I downloaded the keyboard class into the same folder where the java file is located and it is supposed to work but it isn't working.

:confused:
 
  • #71
Does the Keyboard.class file have to exist within a package? Do you need to use the import statement to import it? Can you provide an example of a program which successfully uses this class?

- Warren
 
  • #72
We just did a coin java program like that in my computer science class.
 
  • #73
Ok, so it turns out that error message had to with the capitalization of the title of the keyboard.java document.

I really suck at java.

Ok so now the output just lists the denominations: Quarters, Dimes, Nickels, Pennies. How do I get the appropriate numbers to show up? Does it have something to do with the coding around this part...

change = DOLLAR - amount;
numQuarters = change / QUARTER;
remQuarters = change % QUARTER;
numDimes = remQuarters / DIME;
remDimes = remQuarters % DIME;
numNickels = remDimes / NICKEL;
remNickels = remDimes % NICKEL;
numPennies = remNickels / PENNY;

Do I need brackets or println's or something? Some sort of extra coding to get it to work?

How did you manage to get this done Entropy? Any pointers?

Edit: Fixed one problem. Getting there...
 
Last edited:
  • #74
For my first foray into threads, I wrote a readers/writers (shared resource) simulation. The main() method has an int variable "clock", and it just keeps looping and incrementing clock on each loop. While it loops it creates reader and writer threads, according to a randomly generated schedule; each reader & each writer is a separate thread, and when each one is created it is passed a parameter "duration" telling it the length of time it should be active.

I want each reader or writer thread to release the shared resource after it has been active for its alloted amount of time, so in each constructor I pass "clock" as a parameter, and I set a member int variable of the thread class = to that parameter. I thought that would work since I understood that in Java parameters are passed by reference. But it's not working: the readerthreads and writerthreads are not seeing the updating of the clock value that's occurring in main(). Instead each of those threads just sees a constant clock value -- the value that clock had when the thread was created.

How can I enable the child threads to see the updating of a variable that's occurring in the parent (main) thread?
 
  • #75
gnome said:
The main() method has an int variable "clock",
I understood that in Java parameters are passed by reference.
Objects are passed by reference. ints are not.

How can I enable the child threads to see the updating of a variable that's occurring in the parent (main) thread?
There are numerous ways, some more elegant than others. A simple way is not to pass the value at all. The child threads can access the clock value by ClassName.clock, assuming that the clock variable was declared:
public static int clock;
 
  • #76
ek:

you only asked it to print the words:
for example,
System.out.println ("Quarters");
just says to print exactly what's inside the quotes, in this case the word Quarters.

What you want is
System.out.println (String.valueOf(numQuarters) + " Quarters");
and so on...

(String.valueOf(int i) is a static method of the String class that converts an int to a string.)
 
  • #77
gnome said:
System.out.println (String.valueOf(numQuarters) + " Quarters");
I usually write this System.out.println (numQuarters + " Quarters");
 
  • #78
originally posted by prometheus:
There are numerous ways, some more elegant than others. A simple way is not to pass the value at all. The child threads can access the clock value by ClassName.clock, assuming that the clock variable was declared:
public static int clock;

Does it need to be static? Clock is declared in the main function of the project.
 
  • #79
Originally posted by Prometheus:
I usually write this System.out.println (numQuarters + " Quarters");

Thanks. I didn't realize println() was that smart. :smile:
 
  • #80
gnome said:
Does it need to be static? Clock is declared in the main function of the project.
You mean the main method, not main function.

No, of course not. I said that there are many solutions. This is not a solution that I would use.

However, you are writing your code inside the main method. I suspect, although I may be wrong, that you are new to Java. Otherwise, why write your code in the main method? Since you are writing your code in the main method, you have no objects. By the way, I would declare this variable outside of the main method, at class scope.

TYpically, if I have a variable that I want other objects to see, I pass in the constructor a this reference. The constructed object can then call an accessor method in the creating object to determine the value of the variable. In order to do this, however, the creator must be an object. Your program in the main method does not qualify. Unless you have good reason, I recommend that you do not write Java programs inside of the main method.
 
  • #81
Yes I am definitely new to Java: I wrote hello, world in Java 2 weeks ago for the 1st time.

In this case my main method is just a test driver that instantiates the various ReaderThread and WriterThread objects, and "ticks" the clock. Everything else is in 5 separate class files:
ReaderThread
WriterThread
ReaderCounter
WriterCounter
BinarySemaphore

I tried changing the declaration of clock but I keep getting an "illegal start of expression" error, whether I call it public static int clock; or public int clock; or static int clock;
It only let's me do int clock;
Why?


edit: Got it. I had to move the declaration outside of the main method.
 
Last edited:
  • #82
Thanks Prometheus. It looks like it's running correctly now, but it'll take a while to analyze all the starting and finishing messages from the threads to make sure they're all behaving nicely.
 
  • #83
gnome said:
I tried changing the declaration of clock but I keep getting an "illegal start of expression" error, whether I call it public static int clock; or public int clock; or static int clock;
It only let's me do int clock;
Why?

edit: Got it. I had to move the declaration outside of the main method.
The main method is static, so that all variables declared inside of it are static by context: hence, static is invalid. The main method is a method, so that all variables inside of it are local; hence, public is invalid.

If you have a question, it helps to post your code if it is not too large.
 
  • #84
I believe it's now working the way I intended, but if you don't mind wading through it, I'd welcome any comments, criticisms or suggestions you may offer. Anyway, thanks for your help.


Code:
//	test driver for readers/writers problem
//	There can be multiple readers, or a single writer, active at any time.
//		This solution gives priority to writers: active readers are allowed to
//		finish, but no new readers can start if there is a waiting writer.

import java.util.Random;
import java.util.Arrays;

public class testReadWrite{

	public static int clock;

	public static void main(String[] args){

		final int trial_len = 200;
		final int num_readers = 10;
		final int num_writers = 10;
		final int max_read_time = 10;
		final int max_write_time = 4;

		Random randnum = new Random();
		ReaderCounter rc = new ReaderCounter();
		WriterCounter wc = new WriterCounter();
		BinarySemaphore writing = new BinarySemaphore();
		ReaderThread r;
		WriterThread w;

//		int clock;	//	used to count iterations of the while loop (below)
		clock = 0;
		String s = new String();

		int[] read_arrive = new int[num_readers];
		int[] read_len = new int [num_readers];
		int[] write_arrive = new int [num_writers];
		int[] write_len = new int [num_writers];

		for (int i = 0; i < num_readers; i++){
			read_arrive[i] = randnum.nextInt(100);
			read_len[i] = randnum.nextInt(30) + 5;	//	don't want any 0 durations
		}
		for (int i = 0; i < num_writers; i++){
			write_arrive[i] = randnum.nextInt(100);
			write_len[i] = randnum.nextInt(5) + 5;	//	don't want any 0 durations
		}

		Arrays.sort(read_arrive);
		Arrays.sort(write_arrive);

// next 10 lines are just for evaluating the results
		for (int i = 0; i<num_readers; i++){
			System.out.print("reader" + String.valueOf(i) + " ");
			System.out.println("arr: " + String.valueOf(read_arrive[i]) + " len: "
											+ String.valueOf(read_len[i]));
		}
		for (int i = 0; i<num_writers; i++){
			System.out.print("writer" + String.valueOf(i) + " ");
			System.out.println("arr: " + String.valueOf(write_arrive[i]) + " len: "
											+ String.valueOf(write_len[i]));
		}

		while (clock<trial_len){
			System.out.println("clock = " + String.valueOf(clock));
			for (int i = 0; i < num_readers; i++){
				if (read_arrive[i]==clock){
						// form name of new reader
					s = "reader";
					s = s.concat(String.valueOf(i));
						// create new reader, specifying its read duration
					r = new ReaderThread(s,read_len[i],rc,wc,clock);					
					r.start();
				}
			}
			for (int i = 0; i < num_writers; i++){
				if (write_arrive[i]==clock){
						// form name of new writer
					s = "writer";
					s = s.concat(String.valueOf(i));
						// create new reader, specifying its read duration
					w = new WriterThread(s,write_len[i],rc,wc,writing,clock);					
					w.start();
				}
			}
			
			try{
				Thread.sleep(0,50);
			} catch(InterruptedException e){
			}
			clock++;
		}
	}
}
Code:
//	writer class for readers/writers problem
//	test driver must instantiate ReaderCounter rc, WriterCounter wc
//		BinarySemaphore writing, int clock


public class WriterThread extends Thread{
	 public WriterThread(String s, int d, ReaderCounter rctr, WriterCounter wctr,
														BinarySemaphore bs, int clk){
		super(s);
		name = s;
		duration = d;
		rc = rctr;
		wc = wctr;
		writing = bs;
		clock = clk;
		System.out.println(s + "created.");
	}

	public void run(){
//	reversed the order of the following 2 lines 
		wc.addWriter(); // add to count of waiting writers
		rc.writerPass(); // check ReaderCounter for any active readers
		writing.acquire(); // wait for semaphore to start writing
		finish_time = testReadWrite.clock + duration;
		while(finish_time > testReadWrite.clock)	//	changed from <
{
			try{
				System.out.println(name + ": clock = " + testReadWrite.clock +
							"; finish_time = " + finish_time);
				sleep(0,10); // writer is writing
			} catch(InterruptedException e){
			}
		}
		writing.release(); // finished writing
		wc.delWriter();
	}


	private String name;

	private int clock;
	private int duration;
	private int finish_time;
	private ReaderCounter rc;
	private WriterCounter wc;
	private BinarySemaphore writing;
}
Code:
//	reader class for readers/writers problem
//	test driver must instantiate ReaderCounter rc, WriterCounter wc
//		BinarySemaphore writing, int clock

public class ReaderThread extends Thread{
	public ReaderThread(String s, int d, ReaderCounter rctr,
											 WriterCounter wctr, int clk){
		super(s);
		name = s;
		duration = d;
		rc = rctr;
		wc = wctr;
		clock = clk;
		System.out.println(s + "created.");
	}

	public void run(){
		wc.readerPass(); // readers not allowed to start if a writer is waiting
		rc.addReader(); // makes writers wait while any readers are reading
		finish_time = testReadWrite.clock + duration;
		while(finish_time > testReadWrite.clock)	//	changed from <
{
			try{
				System.out.println(name + ": clock = " + testReadWrite.clock +
										"; finish_time = " + finish_time);
				sleep(0,10);	//	reader is reading
			} catch(InterruptedException e) {
			}
		}
		rc.delReader();		// finished
	}


	private String name;

//	duration  and finish_time will be used by test driver to determine when
//		this thread finishes reading
	private int clock;
	private int duration;
	private int finish_time;
	private ReaderCounter rc;
	private WriterCounter wc;

}
Code:
//	utility class for reader/writers problem
//	test driver will instantiate one ReaderCounter named "rc"

public class ReaderCounter{

	public ReaderCounter(){
		count = 0;
	}

//	used by reader starting to read
	public synchronized void addReader(){
		count++;
		System.out.println(Thread.currentThread().getName() + " starting to read.");
		notifyAll();	//in case another reader tried to start at same time
	}


//	used by reader finished reading
	 public synchronized void delReader(){
		count--;
		System.out.println(Thread.currentThread().getName() + " finished reading.");
		notifyAll();	//in case a writer is waiting
	}

//	used by writer wanting to write
	public synchronized void writerPass(){
		while(count > 0){
			try{
				wait();
			} catch (InterruptedException e){
			}
		}
	System.out.println(Thread.currentThread().getName() + " checking for active readers.");
	}

//	unsynchronized: used by main test loop to see when to terminate
	public int getCount(){
		return count;
	}

	private int count;

}
Code:
//	utility class for reader/writers problem
//	test driver will instantiate one WriterCounter named "wc"

public class WriterCounter{

	public WriterCounter(){
		count = 0;
	}

//	used by writer waiting to write
	public synchronized void addWriter(){
		count++;
		System.out.println(Thread.currentThread().getName() + " added to WriterCounter.");
		notifyAll();	//in case another writer is trying
	}


//	used by writer finished writing
	 public synchronized void delWriter(){
		count--;
		System.out.println(Thread.currentThread().getName() + " removed from WriterCounter.");
		notifyAll();	//in case other writers or readers are waiting
	}

//	used by reader wanting to read
	public synchronized void readerPass(){
		while(count > 0){
			try{
				wait();
			} catch (InterruptedException e){
			}
		}
	}

//	unsynchronized: used by main test loop to see when to terminate
	public int getCount(){
		return count;
	}


	private int count;

}
Code:
//	semaphore class for reader/writers problem

public class BinarySemaphore{

	public BinarySemaphore(){
		value = 1;
	}

	public synchronized void acquire(){
		while (value == 0){
			try{
				wait();
			} catch(InterruptedException e){
			}
 		}
		value = 0;
		System.out.println(Thread.currentThread().getName() + " now writing.");
	}

	 public synchronized void release(){
		System.out.println(Thread.currentThread().getName() + " finished writing.");
		value = 1;
		notifyAll();
	}

	private int value;

}
 
  • #85
Thanks a lot guys, I really appreciate it. After the time I spent on this, it was pretty satisfying to finally get it to work.

Thanks for the help!

:biggrin:
 
  • #86
gnome said:
I believe it's now working the way I intended, but if you don't mind wading through it, I'd welcome any comments, criticisms or suggestions you may offer. Anyway, thanks for your help.
Looks pretty good for someone new to Java. I don't have my Java JVM on this machine to load and test it, so I won't comment on it absent a question.

Note that your String.valueOf() are not necessary, and I prefer to omit them.
This method is called automatically when a primitive is concatenated to a string.
 
  • #87
gnome said:
I believe it's now working the way I intended, but if you don't mind wading through it, I'd welcome any comments, criticisms or suggestions you may offer.
I noticed that your ReaderCounter and WriterCounter classes are 100% identical, except for slight differences in method names. I recommend that you just use the same class for both. If you were to have differences in behavior, an interface or an abstract superclass would be better than two classes that are basically identical. In this case, however, I see no difference in functionality at all.
 
  • #88
Point well taken. Thanks again.
 
  • #89
I'm supposed to write an applet to draw a chessboard using two nested "if" statements. How would I even go about starting this?

Something like attaching numerical values to each square and write "if int=even color black else color white"?

What would the other if statement be? How would you even get the chessboard to look like a chessboard?

This java class is getting to me. It's just getting harder and harder.

Any hints?
 
  • #90
the simplest way to draw a chessboard use
fillRect(int,int,int,int) along with setColor(Color)

choose any start position x,y
choose a neat size for the square as squareSize
run a for loop and change the x as x+squareSize
and at each x,y draw a square (change color as a mod 2 operation)
and once u have drawn 8 squares then change y as y+squareSize

Thus, draw Squares row wise till 8 rows ... and u have a chess board ...

-- AI
 
  • #91
Ok this is what I got so far, it's pretty hopeless, I know.

How do I choose a start position?
How do I get the squares to start repeating? (using a for loop I'm guessing, but how)

import java.applet.Applet;
import java.awt.*;
import java.util.Random;

public class Evan4 extends Applet
{

//stuff here

final int NUM_SQUARES = 64;
final int SQUARE_WIDTH = 30;
int x = 5;
int y = 5;



public void paint (Graphics g)
{


for (int count = 0; count < NUM_SQUARES; count++);

{g.setColor (Color.black);
g.fillRect(x,y,SQUARE_WIDTH,SQUARE_WIDTH);

x += SQUARE_WIDTH;
y += SQUARE_WIDTH;
}
}
}
 
  • #92
public final int INITIAL_X = /*somevalue*/
public final int INITIAL_Y = /*somevalue*/
for(x=INTIAL_X;x<INITIAL_X+SQUARE_WIDTH*8;x+=SQUARE_WIDTH)
for(y=INITIAL_Y;y<INITIAL_Y+SQUARE_WIDTH*8;y+=SQUARE_WIDTH)
{
/*draw rectangle here*/
}

-- AI
 
  • #93
BTW, the notation:

for (int count = 0; count < NUM_SQUARES; count++);

is equivalent to this


for (int count = 0; count < NUM_SQUARES; count++)
;

and actually means an EMPTY for loop. Lose the semicolon.

- Warren
 
  • #94
Ok, I got some help at school today, but it still won't draw properly. It's a problem inside the for loops. It isn't resetting itself to y=0 when the row reaches the LIMIT (8 squares). It just draws them consecutively. Why? How do I fix this?

import java.applet.Applet;
import java.awt.*;

public class Evan4 extends Applet
{

//variables and values

final int LIMIT = 8;
int x = 20;
int y = 20;
int height = 20;
int width = 20;
int ypos;
int xpos;


public void paint (Graphics g)
{

//colour of background
setBackground (Color.gray);

// initial box color
g.setColor (Color.white);
//loop for x
for (int count = 0; count < LIMIT; count++)
//y for loop
{
for (int county = 0; county < LIMIT; count++)
{
//x and y values changing
xpos = x+width*count;
ypos = y+height*county;
//if box is even count draw box black, else white
if ((count + county) % 2 ==0)
g.setColor (Color.black);

else
g.setColor (Color.white);

g.fillRect (xpos, ypos, width, height);


}
}
}
}
 
  • #95
You have made one small but highly annoying error ...

Look at this statement :-
for (int county = 0; county < LIMIT; count++)

Do u see something wrong here?

-- AI
 
  • #96
TenaliRaman said:
You have made one small but highly annoying error ...

Look at this statement :-
for (int county = 0; county < LIMIT; count++)

Do u see something wrong here?

-- AI

No I don't. I suck at java.

:cry:
 
  • #97
It just won't go back to the y origin and draw 8x8. That's pretty much the only problem. It just draws on one y value.

I'm missing something. And it's really making me mad. It's so frustrating.
 
  • #98
ek said:
No I don't. I suck at java.

:cry:
You are incrementing count in a loop that tests county.

- Warren
 
  • #99
chroot said:
You are incrementing count in a loop that tests county.

- Warren

Awesome. Thanks.

Amazing that such a small error can screw you over so badly.

You guys are great.
 
  • #100
Next time you have such an error, consider adding some print statements in strategic places to watch what your program is doing.

I have come across many instances in my career where one single character makes the difference between a perfect program and a disastrous one. Programming requires almost neurotic attention to detail.

- Warren
 

Similar threads

Replies
3
Views
1K
Replies
33
Views
8K
Replies
7
Views
3K
Replies
5
Views
2K
Replies
13
Views
3K
Back
Top