How to write multi-threaded code in Java?

Hi,
I am writing a Java code and in this code, I call an external command by using cmd.exe and I run a batch file. Everything works fine up to this point. However, this is a UI application and after it calls the external command, the UI just waits for the other process to be completed and it you cannot click on any other button in the UI because it is just unresponsive.

As I talk to my colleagues, they recommended me to do multi-threading to solve this problem. Basically, I need to create another thread and then I need to run the external command in this thread. As a result I will be able to use the UI during the time the newly created thread is busy. This way I will use the UI and by using the stop button I will be able to stop this process at any time want.

However, I have never done anything about multi-threading until now and I am in a time pressure. I need to know how to create a new thread and do some processes in this thread.

Can you please help me how I should do this?
TolgarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

MajorBigDealCommented:
Debugging multi-threaded code can be difficult and time-consuming and it does not sound like it is necessary for the problem you have described.   How are you calling cmd.exe? Are you using Runtime.getRuntime().exec?  If so it should not stop and wait for the command to complete unless you have also specified waitFor().  If so, remove the waitFor() and your problem is solved.  

Here is a better explanation:

http://stackoverflow.com/questions/12668854/how-to-tell-java-run-this-runtime-getruntime-exec-without-waiting-what-ever-c
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TolgarAuthor Commented:
I use Runtime.getRuntime().exec and this is the code that I run this external command and even though I don't use waitFor() the code just halts until the process is finished.

Can you please take a look at the code that I have? Could there be a problem/bug at line 22 where I have the while loop?

                    tempDir = "C:/Temp/mgcheck";
                    setMgcheckPathCmd = "cmd.exe /C mg.bat -using A 
                    batchFileCmd = "cmd.exe /C \\\\somePath\\mgcheckGui.bat" +" " + Location + " " + fileInfoLine + " " + checkList ;
                
                perlCmd = batchFileCmd;
                Runtime mgcheck_runtime = Runtime.getRuntime();
                
    
                try {
                    mgcheck_process = mgcheck_runtime.exec(perlCmd, environment);
                } catch (Exception e) {
                    System.out.println("error executing " + perlCmd);
                }
                
    
                /* dump output stream */
                InputStream is = mgcheck_process.getInputStream();
                BufferedReader reader = new BufferedReader
                    ( new InputStreamReader(is));
                String commandLineOutput;
                String resultsXML = null;
                while ((commandLineOutput = reader.readLine()) != null) {
                    Pattern p = Pattern.compile("\\d{8}_\\d{4}_\\d{2}_Mgcheck.xml");
                    Matcher m = p.matcher(commandLineOutput);
                    if (m.find()){
                        resultsXML = m.group();                       
                    }
                    System.out.println(commandLineOutput);
                }
                System.out.flush(); 

Open in new window

0
krakatoaCommented:
If you want to run a lengthy task then as you rightly say, it is best done on a separate thread. You can instantiate, and run(), a(n) (inner) Runnable-implementing class to do this. Then at the point where you need to make use of it, call it and pass the parameters required. From your above code, it looks like you are calling your process inline at the moment.
0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

krakatoaCommented:
Simplified dem, but this shows how a task can run and leave the GUI buttons operational. Hope it helps. Obviously.

import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.util.*;
import java.awt.event.*;

class Asynch extends JFrame implements ActionListener{

static JButton j,jst;
static Asynch a;
static volatile boolean taskunderway = false;
static int times = 1;

  public static void main(String[] args){

	a = new Asynch();

	j = new JButton("Click to start task");

	jst = new JButton("Click to stop task");

	a.setLayout(new BorderLayout());

	a.getContentPane().add(j,BorderLayout.CENTER);
	a.getContentPane().add(jst,BorderLayout.SOUTH);

	a.setSize(new Dimension(350,100));

	a.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

	a.setVisible(true);

	j.addActionListener(a);
	jst.addActionListener(a);
	
  }

 static class Task implements Runnable{

	public void run(){

		try{
	     	Thread.sleep(2000);
		}catch(Exception e2){}
		j.setBackground(java.awt.Color.GREEN);

		taskunderway=true;
		j.setText(" . . . running . . . ");
		while((taskunderway&&a.isVisible())){System.out.println(new Date());}	
		System.out.println("Task ended.");	
		times = 1;	
	}

  }


  public void actionPerformed(ActionEvent e){

		
		if(((JButton)e.getSource()).getText().equals("Click to stop task")&&taskunderway){
			
			taskunderway = false;
			System.out.println("Stopping task");
			j.setText("Click to start task");
			j.setBackground(jst.getBackground());
			return;

		}
		if(((JButton)e.getSource()).getText().equals("Click to stop task")&&!taskunderway){return;}
		
		if(!taskunderway){
		  j.setBackground(java.awt.Color.RED);
		  Thread th = null;	
		  th = (new Thread(new Task()));
		  th.start();
		}
		else{j.setText("Said I'm running "+(times++)+" times now!");/*try{
	     	Thread.sleep(2000);
		}catch(Exception e2){}j.setText(" . . . running . . . ");*/}
						
  }

}

Open in new window

0
TolgarAuthor Commented:
@krakatoa: can you please show me how I can implement it in the code that I posted above.

Thanks,
0
krakatoaCommented:
The idea of my example was how a task from the main thread can be delegated to a separate process, that's all. I thought you were looking for how to approach multi-threaded code.

I am not going to implement it in your code, sorry.

Otoh, there's more reason to adopt CEHJ's proposal, since what I've tried to illustrate is almost certainly not as OOP-PC as Swingworker, and his expert opinion is always to be favoured in this TA.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.