вывести поток из его состояния с помощью уведомления - PullRequest
2 голосов
/ 17 января 2012

Я в отчаянии ... Я работаю весь день над программой, но я не решил мою проблему с cuncurrency потока. Пожалуйста, помогите мне.

У меня есть этот класс, который является универсальным элементомМоя проблема в том, что когда этот объект входит в wait (), он больше не просыпается, даже если я вызываю тот же объект, метод putItemToWork(). Я бы знал, если в коде о cuncurrency есть ошибка, потому что я действительноНе понимаю, где я делаю ошибки ...

Класс объекта

import java.io.*;

public class Item implements Serializable
{
private String id;
private String category;
private String machine;
private boolean isWorked;

private String mchTemp = null; 

public Item(String id,String category,String machine,boolean isWorked)
{
    this.id = id;
    this.category = category;
    this.machine = machine;
    this.isWorked = isWorked;
}

public synchronized void putItemToWork(String id_machine)
{    
    try
        {
            System.out.println("Working the item...");
            Thread.sleep((long)(1+Math.random()*10000));
        }
        catch(InterruptedException ie) {ie.printStackTrace(); }

            mchTemp = id_machine;        
    isWorked = true;
    notify();
}

public synchronized String getWorkedItem()
{
    if(mchTemp == null)
    {
        try
        {   
            wait();
        }
        catch(InterruptedException ie) {ie.printStackTrace(); }
    }

    return mchTemp;
}

public String getId()
{
    return this.id;
}

public String getCategory()
{
    return this.category;
}

public String getMachine()
{
    return this.machine;
}

public boolean isWorked()
{
    return this.isWorked;
}
}
}

ServerMultiThread

import java.io.*;
import java.util.*;
import java.net.*;
import javax.swing.SwingUtilities;
import javax.swing.JTextArea;

public class ServerMultiThread implements Runnable
{   
Socket socket;
private ServerSocket serverSocket;
private LinkedList<Item> itemsList;
private LinkedList<Machine> machinesList;
private static final boolean listening = true;
private JTextArea output;

public ServerMultiThread(LinkedList<Item> itemsList,LinkedList<Machine> machinesList,JTextArea output)
{
    this.itemsList = itemsList;
    this.machinesList = machinesList;

    this.output = output;

    try
    {
        this.serverSocket = new ServerSocket(8090);
    }
    catch(IOException ioe){ioe.printStackTrace(); }

    new Thread(this, "Server").start();
}

@Override
public void run()
{
    Item itemTemp = null;

    SwingUtilities.invokeLater(new Runnable(){@Override public void run(){output.append("Server in run!\n");}});

    while(listening)
    {

        try
        {
            SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("Waiting for incoming connection...\n");}});

            socket = serverSocket.accept();

            SwingUtilities.invokeLater(new Runnable(){@Override public void run(){output.append("Connected to: "+socket.getInetAddress()+":"+socket.getPort()+"!\n");}});

            ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());

            synchronized(itemsList)
            {
                for(Item item : itemsList)
                {
                    if(!item.isWorked())
                    {
                        itemTemp = item;
                        break;
                    }
                }

                new ItemHandler(itemTemp,ous,output);
            }

        }
        catch(IOException ioe) {ioe.printStackTrace(); }
    }
}
}

ItemHandler

import java.io.*;
import java.util.LinkedList;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class ItemHandler implements Runnable
{
String id_machine;
private Item item;
private ObjectOutputStream ous;
//private ObjectInputStream ois;
private JTextArea output;

public ItemHandler(Item item,ObjectOutputStream ous,JTextArea output)
{
    this.item = item;
    this.ous = ous;
    //this.ois = ois;
    this.output = output;

    new Thread(this).start();
}

@Override
public void run()
{
    try
    {
        ous.writeObject(item);                    

        SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("Item Handler "+item.getId()+ " in run!\n");}});

        id_machine = item.getWorkedItem();

        SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("The item "+item.getId()+" was correctly worked by "+id_machine);}});

        //System.out.println("The item "+workedItem.getId()+" was correctly worked by "+workedItem.getMachine());
    }
    catch(IOException ioe){ioe.printStackTrace();}
}
}

MachineApp

import java.io.*;
import java.net.*;

public class MachineApp 
{
private Socket socket;
private String id_machine;

public MachineApp(String id_machine)
{
    this.id_machine = id_machine;

    try
    {
        this.socket = new Socket("localhost",8090);

        System.out.println("Estabilished connection to main server!");
    }
    catch(UnknownHostException uhe) {uhe.printStackTrace();}
    catch(IOException ioe) {ioe.printStackTrace(); }

    execution();
}

private void execution()
{
    try
    {
        //ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());    
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());          

        Item item = (Item) ois.readObject();

        item.putItemToWork(id_machine);

        System.out.println("Item Worked!");
    }
    catch(ClassNotFoundException cnfe) {cnfe.printStackTrace(); }
    catch(IOException ioe) {ioe.printStackTrace(); }
}

public static void main(String[] args)
{
    MachineApp machineApp = new MachineApp(args[0]);        
}
}

Ответы [ 2 ]

3 голосов
/ 17 января 2012

Для меня ваш код работает просто отлично.Вы вызываете wait / notify из разных потоков:

    public static void main(String[] args) {
    final Item item = new Item("id", "cat", "mach", false);

    Thread retrievalThread = new Thread(new Runnable() {
        @Override
        public void run() {
            item.getWorkedItem();
        }
    });

    Thread puttingThread = new Thread(new Runnable() {
        @Override
        public void run() {
            item.putItemToWork("id");
        }
    });

    retrievalThread.start();
    puttingThread.start();
}

EDIT: после добавления клиентского кода в вопрос: я могу ошибаться, но вы отправляете объект item через сокет, а затем пытаетесь вызвать getWorkedItem для него,Это не работает таким образом, потому что, как только вы отправите элемент через сетевой объект на другую сторону (даже если это происходит в одной JVM), это будет другой объект.Поэтому вызов уведомления об этом не вызовет пробуждение от ожидания.

Как решить эту проблему?Ну, вы можете добавить какой-нибудь интерфейс запросов к своему серверному коду, чтобы вы могли запрашивать, какие элементы были обработаны.

Если это не домашняя работа или учебное упражнение, я думаю, что Hadoop может хорошо подойти для ваших нужд

1 голос
/ 17 января 2012

Для начала вам нужно будет сделать mchTemp volatile, потому что вы пишете в это поле в одном потоке, а читаете его из другого. Без volatile изменения, внесенные в один поток, могут быть не видны в другом шаге.

private volatile String mchTemp = null; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...