I have a thread that copies a file and give the progress bar the progress, I have a method the stops the filestream copy and kills the thread, I am trying to implement a jOptionPanel yes_no to ask the user if they are sure they want to delete. But i need to be able to pause the fileInputStream copy until the thread either stops or is continued. The thread waits but the file copy keeps going. how can i fix this? Any help would be great
First is the thread I want to pause
thr = new Thread("cool") {
#Override
public void run() {
while (running == true) {
try {
newWorkFileName();
long length = fileIn.length();
long counter = 1;
int r;
byte[] b = new byte[1024];
fin = new FileInputStream(fileIn);
fout = new FileOutputStream(fileOut);
tvConvertInterface.updateJLabel2("Creating File");
while ((r = fin.read(b)) != -1) {
counter += r;
fout.write(b, 0, r);
prog = (int) Math.round(100 * counter / length);
tvConvertInterface.updateJProgressbar1(prog);
}
fin.close();
fout.close();
tvConvertInterface.disableStopBtn();
tvConvertInterface.updateJLabel2("Work File Created");
running = false;
} catch (NullPointerException | IOException ex) {
tvConvertInterface.disableStopBtn();
tvConvertInterface.updateJLabel2("File is not valid");
Logger.getLogger(TvConvertGutts.class.getName()).log(Level.SEVERE, null, ex);
tvConvertInterface.updateJProgressbar1(0);
running = false;
}
}
}
};
Next is the Method that i want to implement the jOptionPanel
public boolean terminate() throws IOException, InterruptedException {
synchronized (thr) {
thr.wait();//MAKES THREAD WAIT
//I NEED TO PAUSE THE FILESTREAM AND BE ABLE TO RESUME
}
int n = JOptionPane.showConfirmDialog(
null, "SURE YOU WANT TO DELETE?",
"Kill It Dude",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
fin.close(); //CLOSE INPUT STREAM
fout.flush();//FLUSH OUTPUT STREAM
fout.close(); //CLOSE OUTPUT STREAM
thr.interrupt();//KIILL THE THREAD
System.out.println(thr.getState());//PRINT STATE OF THREAD
TvConvertInterface bst = new TvConvertInterface(null, true);
bst.disableStopBtn();//SET PROGRESSBAR TO 0
} else if (n == JOptionPane.NO_OPTION) {
synchronized (thr) {
thr.notify();//DONT DELETE AND CONTINUE
}
} else {
System.out.println("spewin");
}
return false;
}
This terminate method is called by a button click. From a class called TvConvertInterface
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
try {
check.terminate();
} catch (IOException ex) {
Logger.getLogger(TvConvertInterface.class.getName()).log(Level.SEVERE, null, ex);
}
You are using the JAVA concurrency API incorrectly.
The object.wait() will pause the current thread and the object in this case would serve as a monitor object.
What you need to do is the following:
define a boolean shouldPauseThread variable
the while loop should check for the value in this variable; if it is true you should wait on a monitor object
if the user approves the cancelling, then the thread should end its execution, so there needs to be a check for another variable boolean stopThread
if the user wants to continue with processing, you will just reset the shouldPauseThread variable and notify on the previously used monitor object
you need to handle all the transitions from the mentioned states
Related
I'm trying to write code that reads from a Reader in a non-blocking way, i.e. only calling read() after ensuring ready() returns true.
To test the code, I use the PipedReader/PipedWriter combo, and ready() works great, until I close the PipedWriter, which also marks the end of the stream on the side of PipedReader. However, although its ready() method will never again return true, read() instantly returns -1 when called.
In this case, is there a non-blocking way to figure out that a call to read() would not block?
Here's an example that reproduces the issue.
package test;
import java.io.*;
public class Piper
{
public static void main(String[] args) throws Exception
{
int sleepBetweenChars = 100;
boolean throttle = true;
Reader reader = new StringReader("abc");
if (throttle)
reader = throttle(sleepBetweenChars, reader);
while (true)
{
if (reader.ready())
{
int c = reader.read();
System.out.println("Read " + c);
if (c == -1)
break;
}
else
{
System.out.println("Not ready");
Thread.sleep(sleepBetweenChars);
if (!reader.ready())
{
System.out.println("Still not ready, sleep some more");
Thread.sleep(20 * sleepBetweenChars);
if (!reader.ready())
{
int c = reader.read();
System.out.println("Still not ready, we read nonetheless: " + c);
if (c == -1)
break;
}
}
}
}
}
private static Reader throttle(final int sleepBetweenChars, final Reader in) throws IOException
{
final PipedWriter pw = new PipedWriter();
PipedReader pr = new PipedReader(pw);
(new Thread(new Runnable()
{
public void run()
{
System.out.println("Start piping");
int c;
try
{
while ((c = in.read()) != -1)
{
pw.write(c);
Thread.sleep(sleepBetweenChars);
}
pw.close();
System.out.println("Closed PipedWriter");
}
catch (Throwable t)
{
t.printStackTrace();
}
}
})).start();
return pr;
}
}
PipedReader never ready() at end of stream
I agree. That's not what it's for. ready() tells you whether there is data available to be read, not end-of-file conditions. See the Javadoc: ' A piped character stream is ready if the circular buffer is not empty'.
There isn't a way to do what you're trying to do. Streams and Readers are irredemiably blocking. Your code is basically just an elaborate way of implementing blocking yourself, with added latency and added bugs. It's pointless.
I would also question your use of piped readers and writers at all. They are singularly useless things, really only a proof-of-concept for wait() and notify(). Possibly what you're really looking for is a Queue.
I need a help I'm trying to make client server app for copying files in java... I've got MainWnd object which creates TCPServer object and on send button it will create TCPClient object which send initial data to opponent TCPServer and will open given number of Listen Thread (let it be n) (this Listen threads are here only because they accept a file) (every thread listen on different port which send back to TCPClient) TCPClient then creates n other TCPClients threads which send the file... This I've got and it's running. Problem is, that file receiving can be interrupted by receiver when he click on button Interrupt. I can't get information of this interruption to the receiver's TCPServer thread, which should kill this n threads which are downloading the file.
I think the problem is in TCPServer, where is infinit loop, but the Socket in this will cause blocking of loop so I can't enter to Connection class and kill this n threads.
TCP SERVER
public void setSendInterruption() {
this.interruptedSending = true;
//c.setSendInterruption();
}
public TCPServer(int port, int socketNums, Map<Byte, LinkedList<Byte>> realData, File file, int fileLength) {
this.serverPort = port;
this.socketNums = socketNums;
if(file != null)
this.file = file;
if(fileLength != -1)
this.fileLength = fileLength;
if(realData != null)
this.realData = realData;
if(tmpData != null)
this.tmpData = tmpData;
}
#Override
public void run() {
try {
System.out.println(this.getId());
listenSocket = new ServerSocket(serverPort);
System.out.println("server start listening... ... ...");
while(true) {
if(interruptedSending)
System.out.println("Here I never come");
Socket clientSocket = listenSocket.accept();
Connection c = new Connection(clientSocket, socketNums, realData, file, fileLength);
}
}
catch(IOException e) {
System.out.println("Listen :"+e.getMessage());}
}
Connection
while (true)
{
byteRead = input.read();
//Thread.sleep(100);
if(interruptedSending) {
TCPClient tcpClient = new TCPClient(clientSocket.getPort(), clientSocket.getInetAddress().getHostAddress());
tcpClient.sendInterruptedData();
interruptedSending = false;
}
char lowChar;
if(byteRead == -1) {
break;
} else
lowChar = (char)byteRead;
lowData += lowChar;
if(lowData.length() >= 2) {
if (lowData.substring(lowData.length()-2).compareTo("//") == 0) {
break;
} else if (lowData.length() > 6) {
byteData.add((byte)byteRead);
}
}
}
In connection there is more lines, but they are only mainly parsing a protocol.
Thanks a lof for your help. I hope I wrote it clean...
From what I understand each Connection has a Thread that runs it. You want to interrupt each of these threads but can't do that from within the threads because they are stuck in input.read().
If that is what you meant, just do this:
In the constructor of Connection save the Thread, so you can access it later.
Make a killThread()-Method or therelike, so you can access the thread from the outside:
public void killThread() {
thread.interrupt(); //thread is the thread you saved in the constructor
}
When you want to kill the Connection-thread call killThread(). This will cause the Thread to throw a java.lang.InterruptedException, wherever it is at the moment.
This one you can either ignore (since you want the thread to die anyways) or you encase the whole while-loop with a
try {
//your loop
} catch (InterruptedException e) {
return;
}
which will end the thread nicely without throwing the exception out.
I m having a server code to process an image.
Now there are n number of requests which tries to execute the code which results in OutOfMemory error or the server to hang and the server goes to not responding state.
To stop the code from executing at once all the requests I m limiting to execute the code one at a time using the below method where i have a variable
if the variable is 10 then wait for the variable to come at 0
if at 0 then set it to 10 then execute the code
run the code and finally set i to 0
The code here -
static newa.Counter cn;
public int getCounta() {
return cn.getCount();
}
public void setCounta(int i) {
cn = new newa.Counter();
cn.setCount(i);
}
at the function i m doing this -
public BufferedImage getScaledImage(byte[] imageBytes)
{
int i=0;
Boolean b = false;
BufferedImage scaledImage = null;
newa.NewClass1 sc = new newa.NewClass1();
try {
sc.getCounta();
} catch (NullPointerException ne) {
sc.setCounta(0);
}
i = sc.getCounta();
if(i==0)
{
sc.setCounta(10);
b = true;
}
else
{
while( b == false)
{
try
{
Thread.sleep(2000);
i = sc.getCounta();
if( i==0)
{
sc.setCounta(10);
b = true;
System.out.println("Out of Loop");
}
} catch (InterruptedException ex) {
System.out.println("getScaledImage Thread exception: " + ex);
}
}
}
..... execute further code
try { } catch { } finally { sc.setCounta(0); }
}
Is there any way I can have this simplified using the Runnable interface or something as I don't know how to do multi-threading.
Forget about the counter and use a synchronized method. Changed your method head to this:
public synchronized BufferedImage getScaledImage(byte[] imageBytes)
This lets all the threads entering the method wait until no other thread is executing the method.
If you want only a small number of threads doing the processing you can use Executor framework to have a thread pool of 10 threads. This will ensure that at one time maximum of 10 threads will be processing the requests.
I am creating a multiplayer game in Java with a server and multiple clients. Everything runs perfectly, until I press the Kick-button in the server to kick a client.
Error at receive thread of server, after kicking the first person who joined out of three:
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
> at networktest.Server$3.run(Server.java:186)
at java.lang.Thread.run(Thread.java:722)
The pointed line is the ois = new ObjectInputStream where I receive datatype in the server receive thread. The server kicks the first person perfectly, but removes the second one in the list too, with an error of java.lang.ClassCastException.
server receive:
private static Thread receive = new Thread()
{
#Override
public void run()
{
ObjectInputStream ois;
while (true)
{
for (int i = 0; i < list_sockets.size(); i++)
{
try
{
ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
int receive_state = (Integer) ois.readObject(); // receive state
ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
byte datatype = (byte) ois.readObject(); // receive datatype
if(datatype == 2){
ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
ChatLine chatLine = (ChatLine) ois.readObject(); // receive ChatLine
} else if (datatype == 0){
ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
DataPackage dp = (DataPackage) ois.readObject(); // receive dp
list_data.set(i, dp);
}
if (receive_state == 1) // Client Disconnected by User
{
disconnectClient(i);
i--;
}
}
catch (Exception ex) // Client Disconnected (Client Didn't Notify Server About Disconnecting)
{
System.err.println("Error # receive:");
ex.printStackTrace();
disconnectClient(i);
i--;
}
}
try {
this.sleep(3);
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
user send:
Thread send = new Thread()
{
public void run()
{
ObjectOutputStream oos;
byte datatype = 0;
while (connected){
if (socket != null){
try {
DataPackage dp = new DataPackage();
dp.x = Client.player.x;
dp.y = Client.player.y;
dp.username = username;
dp.charType = charType;
dp.walking = (byte)Client.player.walking;
if (Client.outputChatLine.line != null)
datatype = 2;
else {
datatype = 0;
}
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(Integer.valueOf(Client.this.state)); // send state
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(Byte.valueOf(datatype)); // send datatype
if (datatype == 2)
{
oos.reset();
oos.writeObject(Client.outputChatLine);
Client.outputChatLine = new ChatLine();
} else {
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(dp);
}
if (Client.this.state == 1) {
connected = false;
socket = null;
JOptionPane.showMessageDialog(null, "Client Disconnected", "Info", 1);
System.exit(0);
}
}
catch (Exception ex){}
}
try {
this.sleep(2);
} catch (InterruptedException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
disconnect client method:
public static void disconnectClient(int index)
{
try
{
list_clients_model.removeElementAt(index);
list_client_states.remove(index);
list_data.remove(index);
list_sockets.remove(index);
}
catch (Exception ex) {}
}
Does anyone know how to solve this?
It looks like you're expecting some other thread to fill some data into list_sockets while you're sleep(3)ing. But you have no synchronization to ensure that this happens only while you're sleeping.
It could equally well happen that the other thread is updating list_sockets simultaneously with your own thread calling list_sockets.get(i). And the ArrayList implementation it is almost certainly not written to have two different of its methods executing simultaneously in two different threads. For example, the other thread could be in the middle of resizing the backing array when you're trying to read an element, and then any crazy thing can go wrong, including the error you're seeing.
You need to learn about inter-thread synchronization. At the very least you need synchronized blocks to protect access to shared data structures. And while you're at it; look at wait/notify or some higher-level concurrency tools to get rid of that horrible 3-millisecond polling loop -- instead have the thread that drops work into the list explicitly wake up the worker thread.
I have an ObjectOutputStream and an ObjectInputStream. I try to send ints and objects through them. Now I manage to send through and read up to a point and I don't know why it stops there.
Here is the point:
Reader:
while (true) {
start = in.readInt();
System.out.println("PART 1");
int temp1 = in.readInt();
int temp2 = in.readInt();
int temp3 = in.readInt();
System.out.println("PART12");
Chunk temp = new Chunk(temp1,temp2, temp3);
while (true) {
It doesn't get to part12 (doesn't pass the first int...)
Writer:
if (chunkList != null) {
for (Chunk c: chunkList) {
out.writeInt(-1);
out.writeInt(c.getLocation().getX());
out.writeInt(c.getLocation().getY());
out.writeInt(c.getLocation().getZ());
if (c.getTileList() != null) {
it passes all of it successfully.
I am every 2ms out.flushing in a separate thread.
Thread:
while (true)
{
while (c.sendPacket()) {
try
{
if (c.getOut() != null)
{
c.getOut().flush();
}
}
catch (IOException ioexception)
{
ioexception.printStackTrace();
}
try
{
sleep(2L);
}
catch (InterruptedException interruptedexception) { }
}
}
Why does it stop reading at the part with the 3 ints?
I have a feeling that this is a thread-safety issue. As a general rule, streams are not designed to be thread-safe. So, unless the you are synchronizing the two threads at a higher level, one thread writing to a stream and a second thread calling flush is unsafe.