多个线程访问多个对象

时间:2011-09-08 21:59:31

标签: java multithreading

我有一个带有四个文本框的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);
    }
}

1 个答案:

答案 0 :(得分:0)

同步呼叫并不意味着“如果跑道1可用则执行此操作”。这意味着“等到跑道1可用然后这样做”。

为此你应该使用标志和锁:

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

这样,其他线程可以看到标志已设置,而不是尝试获取锁。检查关键部分内的标志也是更可靠的(双重检查锁定),但在这种情况下将其遗漏没有重大后果。

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