• 0

[JAVA] Saving integers from a thread


Question

Hey,

I'm currently doing my assignment, which is a client, server network application. A concurrent server.

Its a concurrent server, and works perfectly for general communication. However i have to store how many times the file has been 'downloaded'.

The server works by creating a thread upon a successful connection. The server then has to print out how many times a file has been downloaded after its downloaded.

The thread when a file is downloaded calls a method in the server to increment the download count. However because its seperate threads when multiple clients connect it doesnt increment the updated number that another client might have set.

Output from my IDE to show what i mean:

Waiting for connection request...

Creating a new thread

Number of threads running: 1

Waiting for connection request...

File 1 has been downloaded 1 times.

Creating a new thread

Number of threads running: 2

Waiting for connection request...

File 1 has been downloaded 1 times.

Obviously File 1 should have been downloaded 2 times.

Any way to fix this?

Thanks,

David

Link to comment
https://www.neowin.net/forum/topic/706174-java-saving-integers-from-a-thread/
Share on other sites

13 answers to this question

Recommended Posts

  • 0

Yeah the integer is a int[], part of the main class.

Relevant code

Main

  public void setDownload(int fileNo) {
	int[] downloadCount = new int[files.length];
	downloadCount[fileNo]++;
	System.out.println(files[fileNo] + " has been downloaded " + downloadCount[fileNo] + " times.");
  }

Thread Instance

case 4:
					out.println("You are downloading " + files[3]);
					serverObject.setDownload(3);
					state = 2;
					break;

  • 0

btw: you have a serious programming problem...

you should only have one server instance, but you seem to have multiple.... so in other words my above fix is not the right solution even though it works.

you should use the singleton pattern to get the server instance and ensure there is only ever one server instance... so do this code instead.

public class ServerObject {
private int[] downloadCount; // note: no longer static

private static ServerObject instance; // the server instance is now static

private ServerObject() {
   // hide the default constructor from everyone except this class
}

public static ServerObject getInstance() {
   if (instance == null) {
	  instance = new ServerObject(); // only called once, so ensures only one server instance.
   }
  return instance;
}
}

out.println("You are downloading " + files[3]);
					ServerObject.getInstance().incrementDownloadCounter(3);
					state = 2;
					break;

// you no longer need to call new ServerObject() - just call  ServerObject.getInstance() anywhere in your code. you dont even need to pass it in as a parameter.

  • 0

no, if you implement the singleton pattern as shown above, you can only ever have one instance of the server object.

calling getInstance() ensure that every thread in the JVM will always reference the same server object.

notice the "static ServerObject instance" declaration. it ensures that all instance of Server object are shared - hence "static"

now we ensure that only one server object can ever exist by making the constructor "private ServerObject()" and

creating the static method

public static ServerObject getInstance() {

if (instance == null) {

instance = new ServerObject(); // only ever called once, so ensures only one server instance.

}

return instance;

}

here is your code at the moment - hence why you had the download count problem.

[server] -> [worker thread]
[server] -> [worker thread]
[server] -> [worker thread]
[server] -> [worker thread]
[server] -> [worker thread]
[server] -> [worker thread]

here is the singleton pattern applied to the server

				|- [worker thread]
				|- [worker thread]
	[server]----|- [worker thread]
				|- [worker thread]
				|- [worker thread]
				|- [worker thread]

  • 0

One more issue, when putting the client into a GUI, which is continuously checking for user input and server input. The GUI doesnt add all the components. This is because I have made it so that the main method contains a while loop, that is checking for server input.

What would be the best way to put it into a GUI, so that the text area updates with all server input? This is the following code, which checks for messages from the server.

		while ((fromServer = in.readLine()) != null) {
			System.out.println("Server: " + fromServer);
		}

  • 0

Thanks i have made quite a bit of progress with that advice.

It now updates the text field with the first input from the server, but because its not in a loop, it doesnt update it.

Again, if i put it in the loop, the frame doesnt paint.

This is my code.

Client

  public static void main(String args[]) {
	// read from server
	thread.start();

	java.awt.EventQueue.invokeLater(new Runnable() {

	  public void run() {
		new Client().setVisible(true);
		  text = ClientThread.getOutputText();
		  setServerText(text);
	  }
	});
  }

  public static void setServerText(String text) {
	textOutput.setText(text);
  }

ClientThread

  @Override
  public void run() {   
	try {
	  while ((fromServer = in.nextLine()) != null) {
		setOutputText("Server: " + fromServer);
	  }
	} catch (NoSuchElementException ex) {
	}
  }

  public void setOutputText(String textInput) {
	serverOut = textInput;
  }

  public static String getOutputText() {
	return serverOut;
  }

The Client definately communicates with the server, as i can see the messages passed in the output dialog of my IDE, from my setOutputText method. I just need a loop for the GUI to update.

Edited by dave164
  • 0

try setting thr thread to sleep for a little bit in your while loop.

Thread.sleep(500);

also you should not be doing this stuff in the main. you should be creating an instance of the class!!!!

ie.

  public static void main(String args[]) {
		ClientApplication clientApplication = new ClientApplication();
	}

  public ClientApplication(String text) {
	this.setVisible(true);
   java.awt.EventQueue.invokeLater(new WorkerThread(this));

}

  public void setServerText(String text) {
	textOutput.setText(text);
  }


class WorkerThread implements Runnable{

  private ClientApplication clientApp;

   public WorkerThread(ClientApplication clientApp) {
	 this.clientApp = clientApp;
   }

   public run() {

	 while (!this.clientApp.isCloseConnectionState())
		 try {  
		 this.clientApp.setTextOutput(..... put txt here)   
		 Thread.sleep(500);
		} catch() {
		   throw runtimeException(e);
		 }
	 }
}

note: code above wont work as you need to code this yourself. and I dont have a compiler on hand

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.