所以我一直在研究一个很长的项目,试图理解多线程的基础知识和套接字的使用,但我似乎偶然发现了一些块,不知道它来自哪里。
应用程序应该模拟作为服务器端的存储,作为客户端/服务器的商店,然后商店本身拥有自己的客户端。
有时我在Warehouse.java的switch / case方法processInput上得到“NullPointerException”(代码将在下面添加),并且程序似乎没有在.run方法的第一个while循环中释放锁定Shop.Java。
Main.Java
package exe6;
public class Main {
static Thread mainThread = Thread.currentThread();
public static void main(String[] args) throws InterruptedException{
Box box = new Box();
PayPalAcc pp1 = new PayPalAcc();
mainThread.setName("mainThread");
Thread DaniCustomerThread = new Thread(new Customer(box, pp1, "Daniel Netzer"), Customer.getName());
Thread POShopThread = new Thread(new Shop(box, pp1, "Post Office"), Shop.getName());
Thread WareHouse = new Thread(new Warehouse(), "Warehouse");
WareHouse.start();
DaniCustomerThread.start();
POShopThread.start();
Thread.sleep(3*60*100);
POShopThread.interrupt();
DaniCustomerThread.interrupt();
}
}
Shop.java
package exe6;
import java.net.*;
import java.io.*;
public class Shop implements Runnable{
private static Box box;
private static PayPalAcc paypal;
private static String name;
// Threads Monitors
private static Object shopBox = new Object();
private static Object shopPP = new Object();
private static Object shopIS = new Object();
// Socket Variables/Properties
private static final String hostName = "Localhost";
private static final int portNumber = 1234;
static boolean isInStorage = false;
// Getters/Setters/Constructors
public Shop(Box box,PayPalAcc paypal, String name){
Shop.box = box;
Shop.name = name;
Shop.setPaypal(paypal);
}
public static Object getShopBoxMonitor(){
return Shop.shopBox;
}
public static int getShopPort(){
return portNumber;
}
public static Object getShopWHMonitor(){
return Shop.shopIS;
}
public static Object getShopPPMonitor() {
return Shop.shopPP;
}
public static String getName() {
return name;
}
private static PayPalAcc getPaypal() {
return paypal;
}
private static synchronized void setPaypal(PayPalAcc paypal) {
Shop.paypal = paypal;
}
//Shop Methods
//Depositing a package into a selected box.
private synchronized void depositBox(){
Shop.box.setBoxStatus(true);
printsShop(1);
synchronized(Customer.getCustomerLockMonitor()){
Customer.getCustomerLockMonitor().notify();}
}
//Withdrawing money from selected PayPal account.
private synchronized void withdrawFromPayPal(int amountToWithdraw){
Shop.getPaypal().setPayPalAccStatus(Shop.getPaypal().getPayPalAccStatus() - amountToWithdraw);
printsShop(2);
}
//Switch/Case to hold all shop printable.
private synchronized void printsShop(int caseNum){
switch(caseNum){
case 1: System.out.println(Shop.getName() +" deposited new package in " +Customer.getName() +" box.");
break;
case 2: System.out.println(Shop.getName() +" withdrawed money from shared PayPal account.");
break;
case 3: System.out.println(Shop.getName() +" box is full, waiting for customer withdrawal.");
break;
case 4: System.out.println(Customer.getName() +" did not deposited money into PayPal account yet.");
break;
case 5: System.out.println("Program have finished, closing safely " +Thread.currentThread().getName() +" thread.");
break;
}
}
public static void clientSocket(){
try (
Socket ShopSocket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(ShopSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(ShopSocket.getInputStream()));) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while (!Shop.isInStorage) {
fromServer = in.readLine();
System.out.println("Warehouse Response: " + fromServer);
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Shop Query: " + fromUser);
out.println(fromUser);
}
}
synchronized(Shop.getShopWHMonitor()){ Shop.getShopWHMonitor().notify(); };
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
//Thread operations.
@Override
public void run() {
while(Main.mainThread.isAlive()){
while (!isInStorage) {
clientSocket();
synchronized(Shop.getShopWHMonitor()){
try {
Shop.getShopWHMonitor().wait();
} catch (InterruptedException e) {
printsShop(5);
Thread.currentThread().interrupt();
break;
}
}
while(Shop.getPaypal().getPayPalAccStatus() < 100){
synchronized(Shop.getShopPPMonitor()){
try {
printsShop(4);
Shop.getShopPPMonitor().wait();
} catch (InterruptedException e) {
printsShop(5);
Thread.currentThread().interrupt();
break;
}
}
withdrawFromPayPal(100);
while(box.isBoxStatus()){
synchronized(Shop.getShopBoxMonitor()){
try {
printsShop(3);
Shop.getShopBoxMonitor().wait();
} catch (InterruptedException e) {
printsShop(5);
Thread.currentThread().interrupt();
break;
}
}
}
}
}
depositBox();
isInStorage = false;
if (Thread.currentThread().isInterrupted()) { break; }
}
}
}
Warehouse.java
package exe6;
import java.net.*;
import java.io.*;
public class Warehouse implements Runnable{
private static final String WAITING = "";
private static final String CHECKREQUEST = "Check if Package is in warehouse.";
static final String SENTREQUEST = "Request Package.";
static final String SENTREQUEST_RESPONSE = "Package have been sent to " +Shop.getName() +".";
private static final String CHECKREQUEST_RESPONSE = "The pacakge is availble in the warehouse.";
private static final String WAITING_RESPONSE = "Waiting for shop query.";
private static final String DEFAULT_RESPONSE = "Query inserted is not legal.";
public static synchronized String processInput(String theInput) {
String theOutput = null;
switch(theInput){
case WAITING: theOutput = WAITING_RESPONSE;
break;
case CHECKREQUEST: theOutput = CHECKREQUEST_RESPONSE;
break;
case SENTREQUEST: { theOutput = SENTREQUEST_RESPONSE;
Shop.isInStorage = true;
synchronized(Shop.getShopWHMonitor()){ Shop.getShopWHMonitor().notify(); }
}
break;
default: theOutput = DEFAULT_RESPONSE;
}
return theOutput;
}
@Override
public void run() {
while(Main.mainThread.isAlive()){
try (
ServerSocket WHSocket = new ServerSocket(Shop.getShopPort());
Socket ShopSocket = WHSocket.accept();
PrintWriter out =
new PrintWriter(ShopSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(ShopSocket.getInputStream()));
) {
String inputLine, outputLine;
// Initiate conversation with client
outputLine = processInput("");
out.println(outputLine);
while (!Shop.isInStorage) {
inputLine = in.readLine();
outputLine = processInput(inputLine);
out.println(outputLine);
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ Shop.getShopPort() + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
}
我也非常感谢任何设计和编码建议。
编辑: 有人提到它是NullPointerException的副本,我想指出这里的主要问题不是Null指针,因为我可以通过避免任何空字符串进入Server Reader函数来轻松克服它,这是我正在尝试的真正问题在这个问题中克服的是无法使用服务器端仓库中的RESPOND作为.notify(),因此,当程序停止推进时,Shop Runnable会等待等待。