2016-04-20 67 views
0

我正在尝试创建4个汽车对象,每个汽车对象都在不同的线程中,但我无法弄清楚如何让每个汽车以不同的速度移动,而这些速度是由用户输入的。在java中使用多线程?

这是我的主要程序:

public class Racecar extends JApplet { 

public Racecar() { 
    setLayout(new GridLayout(5, 1)); 
    JPanel panel1 = new JPanel(); 
    JLabel car1 = new JLabel("Car 1:"); 
    panel1.add(car1); 
    JTextField jtfcar1 = new JTextField(3); 
    panel1.add(jtfcar1); 
    JLabel car2 = new JLabel("Car 2:"); 
    panel1.add(car2); 
    JTextField jtfcar2 = new JTextField(3); 
    panel1.add(jtfcar2); 
    JLabel car3 = new JLabel("Car 3:"); 
    panel1.add(car3); 
    JTextField jtfcar3 = new JTextField(3); 
    panel1.add(jtfcar3); 
    JLabel car4 = new JLabel("Car 4:"); 
    panel1.add(car4); 
    JTextField jtfcar4 = new JTextField(3); 
    panel1.add(jtfcar4); 
    add(panel1, BorderLayout.NORTH); 

    JPanel panel2 = new JPanel(); 
    panel2.setBorder(BorderFactory.createLineBorder(Color.black)); 
    DrawCar car = new DrawCar(1); 
    panel2.add(car); 
    add(panel2); 

    JPanel panel3 = new JPanel(); 
    panel3.setBorder(BorderFactory.createLineBorder(Color.black)); 
    DrawCar car10 = new DrawCar(2); 
    panel3.add(car10); 
    add(panel3); 

    JPanel panel4 = new JPanel(); 
    panel4.setBorder(BorderFactory.createLineBorder(Color.black)); 
    DrawCar car11 = new DrawCar(3); 
    panel4.add(car11); 
    add(panel4); 

    JPanel panel5 = new JPanel(); 
    panel5.setBorder(BorderFactory.createLineBorder(Color.black)); 
    DrawCar car12 = new DrawCar(4); 
    panel5.add(car12); 
    add(panel5); 

} 

public static void main(String[] args) { 
Racecar applet = new Racecar(); 
applet.init(); 
applet.start(); 
JFrame frame = new JFrame(); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.setTitle(""); 
frame.getContentPane().add(applet, BorderLayout.CENTER); 
frame.setSize(400, 320); 
frame.setVisible(true); 


    // Create tasks 
Runnable race1 = new DrawCar(1); 
Runnable race2 = new DrawCar(2); 
Runnable race3 = new DrawCar(3); 
Runnable race4 = new DrawCar(4); 

// Create threads 
Thread thread1 = new Thread(race1); 
Thread thread2 = new Thread(race2); 
Thread thread3 = new Thread(race3); 
Thread thread4 = new Thread(race4); 

// Start threads 
thread1.start(); 
thread2.start(); 
thread3.start(); 
thread4.start(); 
} 

} 

这里是我的DrawCar方法:

public class DrawCar extends JPanel implements ActionListener, Runnable { 
private int delay = 10; 
private Timer timer = new Timer(delay, this); 
private int x1 = 20; 
private int y1 = 22; 
int r = (int)(Math.random()*256); 
int q =(int)(Math.random()*256); 
int b = (int)(Math.random()*256); 
Color color = new Color(r, q, b); 

public DrawCar(int x) { 
timer.start(); 
} 

public void actionPerformed(ActionEvent e) { 
    repaint(); 
} 

protected void paintComponent(Graphics g) { 
super.paintComponent(g); 
g.setColor(color); 
g.fillRoundRect(x1, y1, 75, 20, 10, 10); 
g.fillArc(x1, y1 - 10, 50, 15, 0, 180); 
g.fillOval(x1 + 2, y1 + 10, 20,20); 
g.fillOval(x1 + 40, y1 + 10, 20, 20); 
if(x1 > getWidth()) { 
    x1 = -100; 
} 
    x1 += 1; 

repaint(); 
} 

public Dimension getPreferredSize() { 
    return new Dimension(400, 320); 
    } 

private class TimerListener implements ActionListener { 

public void actionPerformed(ActionEvent e) { 
    repaint(); 
} 
} 

public void run() { 

    try { 

    //int x = Racecar.getSpeed(); 

    Thread.sleep(1500); 

    } 
    catch (InterruptedException ex) { 
    } 

} 

} 
+0

*“我试图创建,其各自单独的线程上4个辆车的对象” * - 那么有一个问题就在那里。相反,你应该有一个更新所有汽车,每辆汽车,一个对象的单一线程,它将拥有自己的速度属性,这将决定每个周期会发生多少变化 – MadProgrammer

回答

0

运行在自己的线程每一辆汽车,如果你希望自己的速度,以定期将无法正常工作。无法保证操作系统何时和多久会安排任何给定的线程。这可能是因为A车的排班次数是B车的两倍,所以即使他们的车速相同,A车看起来也会更快。

另请注意,线程与swing不兼容。

如果必须使用线程,请参见如何做这个教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/simple.html

在我看来,你不应该在所有使用线程完成这个任务 - 只是在一个循环更新的汽车。如果你必须使用线程,至少使用一个线程来更新所有的汽车。

4

我试图创建,其各自单独的线程上

那么有一个问题就在那里4个辆车的对象。有几个原因,最重要的可能是Swing不是线程安全的,所以你冒着竞争条件和不同线程之间的肮脏读/写,可能使“模型”与UI不同步。

相反,你应该有一个更新所有汽车,每辆汽车,一个对象的单一线程,它将拥有自己的速度属性,这将决定每个周期会发生多少变化。

我不会为每辆车创建一个JPanel,而是我将有一个单独的JPanel,它负责绘制所有的汽车。这将为您提供更好的性能,但也更容易处理。

我想先看看Concurrency in Swing了解更多详情。

由于Swing的单线程性质,我还会看看How to use Swing Timers,而不是尝试使用线程。

这是一个令人难以置信的坏主意......

protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    //... 
    if(x1 > getWidth()) { 
     x1 = -100; 
    } 
    x1 += 1; 
    repaint(); 
} 

绘画可以出现了很多不同的原因,其中有许多你不控制,那么你的对象可以是因为被移动速度不算什么该线程正在执行,但是由于系统每次绘制组件时都在做什么,所以基本上它是失控的。

绘画是绘画,没有别的,你不应该从绘画方法中更新组件的状态。

另外,您不应该在paint方法中直接或间接地调用repaint,这很快就会导致一个失控的重绘循环,最终会消耗所有的CPU周期。

也许更多的东西一样......

Race

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private List<Car> cars; 

     public TestPane() { 
      cars = new ArrayList<>(4); 
      Color[] colors = new Color[]{Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA}; 
      int yPos = 0; 
      int speed = 1; 
      for (Color color : colors) { 
       Car car = new Car(new Point(0, yPos += 30), speed++, color); 
       cars.add(car); 
      } 
      Timer timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        for (Car car : cars) { 
         car.update(getSize()); 
        } 
        repaint(); 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      for (Car car : cars) { 
       car.paint(g2d); 
      } 
      g2d.dispose(); 
     } 

    } 

    public class Car { 
     private Point location; 
     private Dimension size; 

     private int speed; 
     private Color color; 

     public Car(Point location, int speed, Color color) { 
      this.location = location; 
      this.speed = speed; 
      this.color = color; 

      size = new Dimension(20, 20); 
     } 

     public void update(Dimension bounds) { 
      location.x += speed; 
      if (location.x + size.width > bounds.width) { 
       location.x = bounds.width - size.width; 
       speed = 0; 
      } 
     } 

     public void paint(Graphics2D g2d) { 
      g2d.setColor(color); 
      g2d.fill(new Rectangle(location, size)); 
     } 

    } 

} 

将有助于