2011-09-08 93 views
0

我有一个四个文本框的GUI窗口,我的代码允许用户创建多个线程。我希望每个线程都能找到一个可用的文本区域并完成其输出语句。我设法一次只得到一个线程执行,但问题在于线程访问所有文本区域并写入它们。多线程访问多个对象

编码在Java中,如下所示:

import java.io.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.Random; 

class thread_action extends Thread 
{ 
    private semaphores view; 
    public thread_action(int threadNumber, semaphores view) 
    { 
     super(" " + threadNumber); 
     this.view = view; 
    } 

    public void land() 
    { 
     //Try to land on Runway 1 
     synchronized(view.output1) { 
      view.output1.append("Plane" + getName() + " approach runway.\n"); 
      try { Thread.sleep (2500); } 
      catch (InterruptedException e) {} 
      view.output1.append("Plane" + getName() + " descending ...\n"); 
      try { Thread.sleep (2500); } 
      catch (InterruptedException e) { } 
      view.output1.append("Plane" + getName() + " clearing runway and taxi to apron.\n\n"); 
     } 
     //Landing completed 

     //Try to land on Runway 2 
     synchronized(view.output2) { 
      view.output2.append("Plane" + getName() + " approach runway.\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output2.append("Plane" + getName() + " descending ...\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output2.append("Plane" + getName() + " clearing runway and taxi to apron.\n\n"); 
     } 
     //Landing completed 

     //Try to land on Runway 3 
     synchronized(view.output3) { 
      view.output3.append("Plane" + getName() + " approach runway.\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output3.append("Plane" + getName() + " descending ...\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output3.append("Plane" + getName() + " clearing runway and taxi to apron.\n\n"); 
     } 
     //Landing completed 

     //Try to land on Runway 4 
     synchronized(view.output4) { 
      view.output4.append("Plane" + getName() + " approach runway.\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output4.append("Plane" + getName() + " descending ...\n"); 
      try { Thread.sleep (1000); } 
      catch (InterruptedException e) { } 
      view.output4.append("Plane" + getName() + " clearing runway and taxi to apron.\n\n"); 
     } 
     //Landing completed 
    } 

    public void run() 
    { 
     Random rand = new Random(); 
     int pickedNumber = rand.nextInt(10); 
     int updateInterval = 1000*pickedNumber; 
     try { Thread.sleep (updateInterval); } 
     catch (InterruptedException e) {} 
     view.status.append("Plane:" + getName() + " has entered the airspace.\n"); 
     long start_time = System.currentTimeMillis(); 
     land(); 
     long end_time = System.currentTimeMillis(); 
     long run_time = (end_time - start_time)/1000; 
     view.status.append("\tPlane" + getName() + " took " + run_time +" seconds to land.\n"); 

    } 
} 

public class semaphores extends Frame implements ActionListener 
{ 
    private static final int WINDOW_HEIGHT = 700; 
    private static final int WINDOW_WIDTH = 1000; 

    private Label labelOne, labelTwo, runway1, runway2, runway3, runway4; 
    private TextField inputOne; 
    private Button runButton, quitButton; 
    public static TextArea status, output1, output2, output3, output4; 

    public semaphores() 
    { 
     setTitle("Airport Simulation"); 
     setSize(WINDOW_WIDTH, WINDOW_HEIGHT); 
     setResizable(false); 
     setLocation(10,20); 
     setLayout(null); 

     labelOne = new Label("Number of Airplanes:"); 
     labelOne.setBounds(5,17,140,40); 
     add(labelOne); 
     inputOne = new TextField(); 
     inputOne.setBounds(150,25,135,25); 
     add(inputOne); 
     inputOne.addActionListener(this); 

     runButton = new Button("Run Program"); 
     runButton.setBounds(5,60,100,25); 
     add(runButton); 
     runButton.addActionListener(this); 

     quitButton = new Button("Quit Program"); 
     quitButton.setBounds(150,60,100,25); 
     add(quitButton); 
     quitButton.addActionListener(this); 

     labelTwo = new Label("Planes Status:"); 
     labelTwo.setBounds(300,20,140,20); 
     add(labelTwo); 
     status = new TextArea(10,40); 
     status.setBounds(300,45,650, 180); 
     add(status); 

     runway1 = new Label("Runway 1:"); 
     runway1.setBounds(10,240,140,20); 
     add(runway1); 
     output1 = new TextArea(10,40); 
     output1.setBounds(10,260,450, 200); 
     add(output1); 

     runway2 = new Label("Runway 2:"); 
     runway2.setBounds(500,240,140,20); 
     add(runway2); 
     output2 = new TextArea(10,40); 
     output2.setBounds(500,260,450, 200); 
     add(output2); 

     runway3 = new Label("Runway 3:"); 
     runway3.setBounds(10,470,140,20); 
     add(runway3); 
     output3 = new TextArea(10,40); 
     output3.setBounds(10,490,450, 200); 
     add(output3); 

     runway4 = new Label("Runway 4:"); 
     runway4.setBounds(500,470,140,20); 
     add(runway4); 
     output4 = new TextArea(10,40); 
     output4.setBounds(500,490,450, 200); 
     add(output4); 
    } 

    public void actionPerformed(ActionEvent event) 
    { 
     int numThreads; 
     String getInput; 
     Button clickedButton = (Button) event.getSource(); 
     if(clickedButton == runButton) 
     { 
      status.setText(""); 
      output1.setText(""); 
      output2.setText(""); 
      output3.setText(""); 
      output4.setText(""); 
      getInput = inputOne.getText(); 
      numThreads = Integer.parseInt(getInput); 
      thread_action[] threads = new thread_action[numThreads]; 
      for(int x=0; x<numThreads; x++) 
      { 
       threads[x] = new thread_action(x, this); 
      } 
      for(int x=0; x<numThreads; x++) 
      { 
       threads[x].start(); 
      } 
     } 
     else 
     { 
      System.exit(0); 
     } 
    } 

    public static void main(String[] args) 
    { 
     semaphores threadObj = new semaphores(); 
     threadObj.setVisible(true); 
    } 
} 
+0

这里有问题吗?我建议你真的想看看SwingWorker的例子。请参阅http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html或更好的http://download.oracle.com/javase/tutorial/uiswing/concurrency/worker.html – Alistair

+0

欢迎到StackOverflow。当你发布一些代码时,尝试省略不相关的代码(例如:Swing Init)。这样你将成为他们所称的SSCCE:http://sscce.org/。 –

+0

究竟是什么问题?我运行了你的代码,并且我得到了Plane 1方法跑道。 飞机1降序... 飞机1清理跑道和出租车到停机坪。 飞机0接近跑道。 飞机0降序... 飞机0清理跑道和出租车到围裙。 飞机2接近跑道。 飞机2降序... 飞机2清理跑道和出租车到停机坪。 所有4文本框 –

回答

0

的同步调用并不意味着“这样做,如果跑道1可用”。这意味着“等到一号跑道可用后再做这个”。

为此,您应该使用标志以及锁:

if (runway1available) { 
    synchronized(runway1) { 
     runway1available=false; 
     landonrunway1() 
     runway1available=true; 
    } 
} 
else if (runway2available) { 
    // ... 
} 

这样,其他线程可以看到设置了标志,而不是试图获得锁。检查关键部分内的标志也会更加可靠(双重检查锁定),但在这种情况下不会产生重大后果。

您还需要小心锁定对象的选择 - 在大多数情况下,最好使用专用的锁定对象,您知道它不会更改或从另一个线程访问。

+0

感谢您的答案:-)将标志添加到全局类,它的工作原理。 – Kamalan