Enquanto uma animação está executando a outra trava - runnable e thread

Alô turma do Guj!
Tô tentando fazer uma brincadeira aqui, usando a classe runnable e thread. Conheço um pouco de java, mas essas classes estou começando a usar. O problema que apareceu é: Eu executo a classe ‘Pinball’ clico no button ‘start’ e a label azul(que depois vai ser a bola) se move no eixo y ate um ponto aleatorio e outro método faz ela ir à esquerda e então a idéia é rebater com uma label ‘Raq’ . Tá tudo no começo. o problema é que enquanto a label azul está se movendo prá esquerda e mesmo depois que ela pára a label amarela ‘raq’ trava e não consigo movê-la com as setas ‘->’ e as demais. Só consigo fazer funcionar as setas reiniciando a aplicação ou antes de clicar em ‘start’. Porque esse travamento enquanto as classes que movem o quadrado azul(‘bola’) estão em execução? Onde está o êrro? Me ajudem, por favor! Abaixo estão as classes envolvidas no programa.

package Run_;

import javax.swing.;
import java.awt.
;
import java.awt.event.*;
import java.awt.event.KeyEvent;
import java.lang.Math;
import java.util.Random;

public class Pinball extends JFrame implements ActionListener, KeyListener, ItemListener, FocusListener // setEnabled
{
private Container c;
public static JLabel lBall, lEsq, lBaixo, lDir, lRaq, lPts, lExPts;
private JLabel lTitTema, lPow;
private JButton bSair, bStart, bReset;
private ImageIcon iconTema, iconOk, iconSair, iconEstat, iconReset, iconVerif, iconIr, iconQuest, icon;
public static JButton bDir, bStop;
private JTextField t1;
static int lRaqY = 0, lRaqX = 0;
static int lBallY = 0, lBallX = 0;
static int cont = 0, max=0, min=0;
static int num_Al = 0;

public Pinball()
{
	super( " Pinball " );
	c = getContentPane();
    c.setLayout(null);
    c.setBackground(new java.awt.Color(255, 90, 50));

    t1 = new JTextField();
   
    t1.addKeyListener(this);

    iconTema = new ImageIcon("TitTema.jpg");
    iconOk = new ImageIcon("Tick.png");
    iconSair = new ImageIcon("exit.png");
    iconEstat = new ImageIcon("estat.png");
    iconReset = new ImageIcon("reset.png");
    iconVerif = new ImageIcon("verif.png");
    iconIr = new ImageIcon("ir.png");
    iconQuest = new ImageIcon("questao.png");
    icon = new ImageIcon("background.jpg");
    
    

    lBall  = new JLabel("");
    lBall.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lBall.setBackground(new java.awt.Color(0, 210, 255));
    lBall.setOpaque(true);

    lTitTema  = new JLabel(" P I N B A L L ", JLabel.CENTER);
    lTitTema.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lTitTema.setBackground(new java.awt.Color(148, 227, 0));//223
    lTitTema.setOpaque(true);

    lEsq  = new JLabel("");
    lEsq.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lEsq.setBackground(new java.awt.Color(148, 227, 0));//223
    lEsq.setOpaque(true);

    lBaixo  = new JLabel("");
    lBaixo.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lBaixo.setBackground(new java.awt.Color(148, 227, 0));//223
    lBaixo.setOpaque(true);

    lDir  = new JLabel("");
    lDir.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lDir.setBackground(new java.awt.Color(148, 227, 0));//223
    lDir.setOpaque(true);

    lRaq  = new JLabel("");
    lRaq.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lRaq.setBackground(new java.awt.Color(255, 235, 0));
    lRaq.setOpaque(true);

    lPts  = new JLabel("PONTOS:", JLabel.CENTER);
    lPts.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lPts.setBackground(new java.awt.Color(255, 235, 0));
    lPts.setOpaque(true);

    lExPts  = new JLabel("0", JLabel.CENTER);
    lExPts.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    lExPts.setBackground(new java.awt.Color(192, 255, 255));
    lExPts.setOpaque(true);

    bDir  = new JButton(" >>> ");
    bDir.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    
    bSair  = new JButton("Sair",iconSair);
    bSair.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));

    bStart  = new JButton("Start");
    bStart.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    bStart.setVisible(true);

    bStop  = new JButton("Stop");
    bStop.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
    bStop.setVisible(false);

    bReset  = new JButton("Reset");
    bReset.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));    

    c.add(t1);
    c.add(lBall);
    c.add(lBaixo);
    c.add(lTitTema);
    c.add(lEsq);
    c.add(lDir);
    c.add(lRaq);
    c.add(lPts);
    c.add(lExPts);
    c.add(bStop);
    c.add(bReset);
    c.add(bSair);
    c.add(bDir);
    c.add(bStart);
    
    lBall.setBounds(790,60,20,20);
    lTitTema.setBounds(30,35,790,25);
    lBaixo.setBounds(30,400,790,10);
    lEsq.setBounds(30,60,10,340);
    lDir.setBounds(810,60,10,340);
    
    lRaq.setBounds(40,195,20,70);
    lPts.setBounds(365,420,65,25);
    lExPts.setBounds(435,420,40,25);

    bStart.setBounds(30,420,70,25);
    bStart.addActionListener(this);
    bStop.setBounds(30,420,70,25);
    bStop.addActionListener(this);
    bReset.setBounds(670,420,70,25);
    bReset.addActionListener(this);
    bSair.setBounds(750,420,70,25);
    bSair.addActionListener(this);
    
    lRaqY = lRaq.getY();
    lRaqX = lRaq.getX();
    
    lBallY = lBall.getY();
    lBallX = lBall.getX();
    
    

    setSize(865,500);
	setVisible(true);
	setResizable(true);

//	setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}
//--------------------------------------------------------------------------------------------------------------------------------------
// ACTION PERFORMED
//--------------------------------------------------------------------------------------------------------------------------------------

public static void main	(String args[]) //throws ParseException
{
   Pinball pb = new Pinball();
}

public void actionPerformed(ActionEvent evt)

{
// START

	if(evt.getSource() == bStart){    

    bStart.setEnabled(false);
    max = 380; 
    min = 60;
    num_Al = min + (int)(Math.random() * (max - min)); 
           
	movBall_Down();
}

//-------------------------------------------------------------------------------------------------------------------------
// RESET

if(evt.getSource() == bReset) {
	
	lBall.setBounds(790,60,20,20);
	bStart.setEnabled(true);
}

//-------------------------------------------------------------------------------------------------------------------------
// STOP
if(evt.getSource() == bStop) {

	bStart.setVisible(true);
	bStop.setVisible(false);
}

//--------------------------------------------------------------------------------------------------------------------------------------
// SAIR
//--------------------------------------------------------------------------------------------------------------------------------------

     if(evt.getSource() == bSair)
  {
    // passando this e nao null, mensagem aparece centro da janela
    int selectedOption = JOptionPane.showConfirmDialog(this,"Deseja Sair Realmente?", "Atencao", JOptionPane.YES_NO_OPTION);
    if(selectedOption == JOptionPane.YES_OPTION){
     dispose();
    // System.exit(0);
               }
  }

} // fim Action Performed

//--------------------------------------------------------------------------------------------------------------------------------------
// FUNCOES
//--------------------------------------------------------------------------------------------------------------------------------------

                        //--------- movRaqUp() ---------------
        	            //
        	              public static void movRaqUp()
        	            {
                          RunMovRaq_Up u = new RunMovRaq_Up ( 60 );
                          Thread mu = new Thread( u );
                          mu.start();
       	                }
        	              //--------- movRaqDown() ---------------
          	            //
          	              public static void movRaqDown()
          	            {
          	            	RunMovRaq_Down d = new RunMovRaq_Down ( 330 );
                            Thread md = new Thread( d );
                            md.start();
         	            }
        	              //--------- movRaqRight_01() ---------------
          	            //
          	              public static void movRaqRight_01()
          	            {   
          	            	RunMovRaq_Right_01 r1 = new RunMovRaq_Right_01 (  );
                            Thread mr1 = new Thread( r1 );
                            mr1.start();
                        }
        	              //--------- movBall_Down() ---------------
          	            //
          	              public static void movBall_Down()
          	            {   
          	            	RunMovBall_Down mb = new RunMovBall_Down (  );
                            Thread mbd = new Thread( mb );
                            mbd.start();
                        }
        	              //--------- movBall_Left() ---------------
          	            //
          	              public static void movBall_Left()
          	            {   
          	            	RunMovBall_Left mvb = new RunMovBall_Left (  );
                            Thread mbl = new Thread( mvb );
                            mbl.start();
                        }
        	              //--------- verif_col() ---------------
          	            //
          	              public static void verif_col()
          	            { 
          	            	  if(lBall.getX() <= (lRaq.getX() + 20) && lBall.getY() <= (lRaq.getY() + 70) &&
          	            	    (lBall.getY() + 20) >= lRaq.getY()) 
          	            	  {
          	            	    stop_mov();
          	            	  }
         	            }
        	              //--------- stop_mov() ---------------
          	            //
          	              public static void stop_mov()
          	            {       	            	     
          	            	RunMovBall_Left.contInicial = 39;              	            	 
         	            }

//-------------------------------------------------------------------------------------------------------------------------------------

        	              public void keyPressed(KeyEvent e)
                        {
                        	    int codigo = e.getKeyCode();

//------------------------------------------- p/ RAQ BAIXO --------------------------------------------

                                	 if (e.getKeyCode() == 40)
                                {
                                         movRaqDown();
                                }

//------------------------------------------- p/ RAQ DIREITA ------------------------------------------

                                	 if(e.getKeyCode() == 39 )
                                {
                                   		movRaqRight_01();
                                }

//--------------------------------------------- p/ RAQ CIMA -------------------------------------------

                                	 if(e.getKeyCode() == 38 )
						        {
						                movRaqUp();
						        }                                    	                                    	 

//-------------------------------------------------------------------------------------------------
}

        	              public void keyReleased(KeyEvent e)
						{
             	            	  if(e.getKeyCode() == 39 )
                                 {
        	            	         // uma tecla foi solta
        	            	         lRaq.setBounds(40,lRaq.getY(),20,70);
                                 }
						}
						
						 public void keyTyped(KeyEvent e)
						{
						    // uma tecla foi pressionada
					    }

		@Override
		public void focusGained(FocusEvent arg0) {
			// TODO Auto-generated method stub				
		}

		@Override
		public void focusLost(FocusEvent arg0) {
			// TODO Auto-generated method stub				
		}

		@Override
		public void itemStateChanged(ItemEvent arg0) {
			// TODO Auto-generated method stub				
		}

}
package Run_;

public class RunMovRaq_Right_01 implements java.lang.Runnable
{
// �rea de dados da Thread
public static int contMov;
// public static int flag=0;
public static int limite=30;

// inicializador da MinhaThread
public RunMovRaq_Right_01 (  )
{
    this.limite = limite; // enviando limite = 0
}    
      public void run()
 {
	                if (limite > 0)
         { 
                             Pinball.lRaqX = Pinball.lRaqX + 2;
                             Pinball.lRaq.setBounds(Pinball.lRaqX,Pinball.lRaqY,20,70);
                             limite--;
                         
                      try {                         
                                Thread.sleep( 1 );                                 
                          }
                      catch (InterruptedException e)
                      {
                             e.printStackTrace( System.err );
                      }                         
         }else {   	        	      
        	     limite = 30;
        	     Pinball.lRaqX = 40;
        	     Pinball.lRaq.setBounds(40,Pinball.lRaqY,20,70);
        	   }
 }
 public static void start()
 {
	 RunMovRaq_Right_01.start();
 }

}
package Run_;

import javax.swing.;
import java.awt.event.
;
import java.awt.;
import java.applet.
;
import java.io.*;

public class RunMovRaq_Up implements java.lang.Runnable
{
// �rea de dados da Thread
public static int contMov;
// public static int flag=0;
public static int limite;

// inicializador da MinhaThread
public RunMovRaq_Up ( int limite ) // limite = 60

{
this.limite = limite;
limite = 60;
this.contMov = contMov;
contMov = Pinball.lRaq.getY();
}

  public void run()
 {
          if (contMov > limite)
         {   	         
                    	     Pinball.lRaqY = Pinball.lRaqY - 5;
           	                 Pinball.lRaq.setBounds(40,Pinball.lRaqY,20,70);
           	              
                          try {      
           	                    Thread.sleep( 0 );                                  
                          }
                              catch (InterruptedException e)
                          {
                             e.printStackTrace( System.err );
                          }
         }
 }
 public static void start() {
	                          RunMovRaq_Up.start();
                            }

}
package Run_;

import javax.swing.;
import java.awt.event.
;
import java.awt.;
import java.applet.
;
import java.io.*;

public class RunMovRaq_Down implements java.lang.Runnable
{
// �rea de dados da Thread
public static int contMov;
// public static int flag=0;
public static int limite;

// inicializador da MinhaThread
public RunMovRaq_Down ( int limite )
	 {
         this.limite = limite;
         limite = 330;
         this.contMov = contMov;
         contMov = Pinball.lRaq.getY();
     }      
  public void run()
 {
          if (contMov < limite)
         {   	              
        	  Pinball.lRaqY = Pinball.lRaqY + 5;
              Pinball.lRaq.setBounds(40,Pinball.lRaqY,20,70);
                      try {
                             Thread.sleep( 0 );                                  
                          }
                      catch (InterruptedException e)
                          {
                             e.printStackTrace( System.err );
                          }
         }
 }
 public static void start() {
	                          RunMovRaq_Down.start();
                            }

}
package Run_;

import javax.swing.;
import java.awt.event.
;
import java.awt.;
import java.applet.
;
import java.io.*;

public class RunMovBall_Down implements java.lang.Runnable
{
// �rea de dados da Thread
public static int contInic;
// public static int flag=0;
public static int limite, pt;

// inicializador da MinhaThread
public RunMovBall_Down (  )
	 {
         this.limite = Pinball.num_Al;
         this.contInic = 60;
     }
 
  public void run()
 {    	 
	  if (contInic <= limite)
      {         
			  while( contInic <= limite ) 
			  {    				
				  Pinball.lBall.setBounds(790,contInic,20,20);
				  contInic++;
				 try {
				        Thread.sleep( 1 );     				  
			     }    			     
		          catch (InterruptedException e)
		          {
			        e.printStackTrace( System.err );
		          }                    }
		}
	  Pinball.movBall_Left();
 }
 public static void start()
 {
	 RunMovBall_Down.start();
 }

}
package Run_;

import javax.swing.;
import java.awt.event.
;
import java.awt.;
import java.applet.
;
import java.io.*;

public class RunMovBall_Left implements java.lang.Runnable
{
// �rea de dados da Thread
public static int contInicial;
// public static int flag=0;
public static int limite;

// inicializador da MinhaThread
public RunMovBall_Left (  )
	 {
         this.limite = limite; 
         this.contInicial = 790;
     }
public void run()
 {
      if (contInicial > 40)
      {                      
         	 while( contInicial >= 40) 
			 {
				  Pinball.lBall.setBounds(contInicial,Pinball.num_Al,20,20);
				  contInicial--;
				  Pinball.verif_col();
				    				  
				  try {
				          Thread.sleep( 1 ); 
  			          }    		  
		           catch (InterruptedException e)
		           {
			         e.printStackTrace( System.err );
		           }
				}
	     }
	      else{
    	         Pinball.lBall.setBounds(790,contInicial,20,20);
              }
      }
       public static void start()
      {
	     RunMovBall_Left.start();
      }

Duplicado: Enquanto uma animação está executando a outra trava - runnable e thread - #2 por staroski