如何在 Java 中的另一个线程中创建一个完全独立的线程?
How to create a totally independent Thread inside another Thread in Java?
作为我研究的一部分,我尝试在 Java RMI 中实现客户端-服务器软件来解决哲学家就餐问题 (https://en.wikipedia.org/wiki/Dining_philosophers_problem)。
网络必须能够识别意外断开连接(例如崩溃)的客户端并恢复其状态。目前我的服务器应用程序跟踪网络中的所有客户端(注册新客户端、重置其他客户端以分配椅子)但不跟踪它们的状态。
因此我想使用一个主动系统,一旦其中一个客户端无法连接到另一个客户端,它将在服务器上使用 RMI 函数删除客户端(首先从 ArrayList 中删除它服务器,然后通过重置所有客户端将其完全删除):
来自 Server.java
的片段
@Override
public synchronized boolean deleteClient(String IP) throws RemoteException, ServerNotActiveException {
if(clients.contains(IP)) {
log.log(Level.FINE, "Remove inactive client {0} from ArrayList...", IP);
clients.remove(IP);
return true;
}
return false;
}
@Override
public void removeClient(String IP) throws RemoteException, ServerNotActiveException {
log.log(Level.FINE, "Removing inactive client {0} from the system...", IP);
resetClientsForRemoval();
}
来自 Client.java
的片段
catch (ConnectException e) {
log.log(Level.SEVERE, "Client seems to be down\n", e);
if (server.deleteClient(IP)) {
new Thread(new Runnable() {
public void run() {
try {
server.removeClient(IP);
} catch (RemoteException e) {
log.log(Level.SEVERE, "Error during removal.\n", e);
} catch (ServerNotActiveException e) {
log.log(Level.SEVERE, "Error during removal.\n", e);
}
}
}).start();
}
}
这意味着我首先检查我是否可以从 ArrayList 中删除客户端(或者其他人是否已经删除它),然后通过重置网络中的所有客户端来执行客户端的最终删除。
但是现在我遇到了一个问题。 Client.java 的代码片段被来自 class Philosopher.java 调用的多个函数使用(例如,在远程客户端上获取叉子或椅子期间)。要重置所有客户端,我首先停止 Client.java 中的所有线程并加入它们:
来自 Philosopher.java 的代码段停止线程(在 运行()
中使用 while(运行ning) 循环
public void terminate() {
running = false;
}
从 Client.java 到 stop/join 话题的片段
@Override
public void stopClient() throws RemoteException, ServerNotActiveException {
for (int i = 0; i < threads.size(); i++) {
log.log( Level.FINE, "{0} temporarily leaving the monastery.", philosophers.get(i).toString());
try {
philosophers.get(i).terminate();
threads.get(i).join();
} catch (InterruptedException e) {
log.log(Level.SEVERE, "Couldn't join thread!\n{0}", e);
}
}
log.log( Level.FINE, "Client stopped.");
}
但我似乎无法加入在内部线程中调用 resetClientsForRemoval 的线程 class。
我的问题:
是否有不同的方法来调用删除函数以将它们与调用线程完全分开?否则它会是一个循环锁,因为我试图通过在该线程正在执行的函数中调用 join 函数来加入一个线程。
在此先感谢您的帮助!
干杯,
斯蒂芬
如果需要,从 Client.java 重置功能
@Override
public void resetClient(int numberOfChairs, String[] neighbors) throws RemoteException, ServerNotActiveException {
chairs = new Semaphore [numberOfChairs];
for (int i = 0; i < chairs.length; i++) {
chairs[i] = new Semaphore(1);
}
//generate local forks
forks = new Semaphore [numberOfChairs];
for (int i = 0; i < forks.length; i++) {
forks[i] = new Semaphore(1);
}
this.neighbors = neighbors;
threads = new ArrayList<Thread>();
for (int i = 0; i < philosophers.size(); i++)
threads.add(new Thread(philosophers.get(philosophers.size() - 1)));
int i = 0;
for (Thread t : threads) {
log.log(Level.FINE,"{0} entering the updated monastery.", philosophers.get(i).toString());
t.start();
i++;
}
}
我在单独的线程中调用 removeClient() 的方法实际上是正确的,但我停止线程的方法却不正确。简单地将 运行 (while(运行)) 的布尔值设置为 false 不足以停止这种情况下的每个线程(老实说,我不知道为什么)。在调用 join 之前,我必须先调用 thread.interrupt()。现在代码按预期工作 => 在另一个线程中启动的线程不会阻止在 "parent" 线程中成功执行连接。
作为我研究的一部分,我尝试在 Java RMI 中实现客户端-服务器软件来解决哲学家就餐问题 (https://en.wikipedia.org/wiki/Dining_philosophers_problem)。
网络必须能够识别意外断开连接(例如崩溃)的客户端并恢复其状态。目前我的服务器应用程序跟踪网络中的所有客户端(注册新客户端、重置其他客户端以分配椅子)但不跟踪它们的状态。
因此我想使用一个主动系统,一旦其中一个客户端无法连接到另一个客户端,它将在服务器上使用 RMI 函数删除客户端(首先从 ArrayList 中删除它服务器,然后通过重置所有客户端将其完全删除):
来自 Server.java
的片段@Override
public synchronized boolean deleteClient(String IP) throws RemoteException, ServerNotActiveException {
if(clients.contains(IP)) {
log.log(Level.FINE, "Remove inactive client {0} from ArrayList...", IP);
clients.remove(IP);
return true;
}
return false;
}
@Override
public void removeClient(String IP) throws RemoteException, ServerNotActiveException {
log.log(Level.FINE, "Removing inactive client {0} from the system...", IP);
resetClientsForRemoval();
}
来自 Client.java
的片段catch (ConnectException e) {
log.log(Level.SEVERE, "Client seems to be down\n", e);
if (server.deleteClient(IP)) {
new Thread(new Runnable() {
public void run() {
try {
server.removeClient(IP);
} catch (RemoteException e) {
log.log(Level.SEVERE, "Error during removal.\n", e);
} catch (ServerNotActiveException e) {
log.log(Level.SEVERE, "Error during removal.\n", e);
}
}
}).start();
}
}
这意味着我首先检查我是否可以从 ArrayList 中删除客户端(或者其他人是否已经删除它),然后通过重置网络中的所有客户端来执行客户端的最终删除。
但是现在我遇到了一个问题。 Client.java 的代码片段被来自 class Philosopher.java 调用的多个函数使用(例如,在远程客户端上获取叉子或椅子期间)。要重置所有客户端,我首先停止 Client.java 中的所有线程并加入它们:
来自 Philosopher.java 的代码段停止线程(在 运行()
中使用 while(运行ning) 循环public void terminate() {
running = false;
}
从 Client.java 到 stop/join 话题的片段
@Override
public void stopClient() throws RemoteException, ServerNotActiveException {
for (int i = 0; i < threads.size(); i++) {
log.log( Level.FINE, "{0} temporarily leaving the monastery.", philosophers.get(i).toString());
try {
philosophers.get(i).terminate();
threads.get(i).join();
} catch (InterruptedException e) {
log.log(Level.SEVERE, "Couldn't join thread!\n{0}", e);
}
}
log.log( Level.FINE, "Client stopped.");
}
但我似乎无法加入在内部线程中调用 resetClientsForRemoval 的线程 class。
我的问题:
是否有不同的方法来调用删除函数以将它们与调用线程完全分开?否则它会是一个循环锁,因为我试图通过在该线程正在执行的函数中调用 join 函数来加入一个线程。
在此先感谢您的帮助!
干杯,
斯蒂芬
如果需要,从 Client.java 重置功能
@Override
public void resetClient(int numberOfChairs, String[] neighbors) throws RemoteException, ServerNotActiveException {
chairs = new Semaphore [numberOfChairs];
for (int i = 0; i < chairs.length; i++) {
chairs[i] = new Semaphore(1);
}
//generate local forks
forks = new Semaphore [numberOfChairs];
for (int i = 0; i < forks.length; i++) {
forks[i] = new Semaphore(1);
}
this.neighbors = neighbors;
threads = new ArrayList<Thread>();
for (int i = 0; i < philosophers.size(); i++)
threads.add(new Thread(philosophers.get(philosophers.size() - 1)));
int i = 0;
for (Thread t : threads) {
log.log(Level.FINE,"{0} entering the updated monastery.", philosophers.get(i).toString());
t.start();
i++;
}
}
我在单独的线程中调用 removeClient() 的方法实际上是正确的,但我停止线程的方法却不正确。简单地将 运行 (while(运行)) 的布尔值设置为 false 不足以停止这种情况下的每个线程(老实说,我不知道为什么)。在调用 join 之前,我必须先调用 thread.interrupt()。现在代码按预期工作 => 在另一个线程中启动的线程不会阻止在 "parent" 线程中成功执行连接。