我很绝望......我整天都在一个程序上工作,但我没有解决我关于线程功能的问题。请帮助我。
我有这个类是一个通用的Item.My问题是当这个对象进入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;
}
}
}
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(); }
}
}
}
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();}
}
}
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]);
}
}
答案 0 :(得分:3)
对我来说,你的代码工作正常。你是从不同的线程调用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();
}
编辑:将客户代码添加到问题后: 我可能是错的,但是您通过套接字发送项目对象,然后尝试在其上调用getWorkedItem。它不能以这种方式工作,因为一旦你通过另一方的网络对象发送项目(即使它发生在一个JVM中)将是不同的对象。因此,在其上调用notify不会触发从等待唤醒。
如何解决?好吧,您可以在服务器代码中添加某种查询界面,以便查询哪些项目有效。
如果没有家庭作业或学习练习,我认为Hadoop可以很好地满足您的需求
答案 1 :(得分:1)
对于初学者,您需要制作mchTemp
volatile
,因为您在一个帖子中写入此字段,并从另一个线程中读取该字段。 没有 volatile
,在一个帖子中所做的更改可能在另一个网格中不可见。
private volatile String mchTemp = null;