Внезапное завершение работы JVM при создании потоков и выполнении сетевых операций в них
Это проблема, которую я пытаюсь исправить, возможно, ошибка в JRE, пожалуйста, проголосуйте, чтобы снова открыть этот вопрос. Это очень эгоистичный подход - отмечать что-то не по теме, если вы недостаточно компетентны, чтобы понять какую-то проблему.
Версия Java
Java-версия "1.7.0_45" Java(TM) SE Runtime Environment (сборка 1.7.0_45-b18) Java HotSpot(TM) 64-разрядная серверная виртуальная машина (сборка 24.45-b08, смешанный режим)
Следование обеим версиям кодов приводит к одной и той же аварии.
Клиентский компьютер вызывает сервлет, развернутый в Tomcat 7 с использованием Server Maching, работающего в 64-разрядной версии Windows Server 2003, с использованием базы данных Oracle 10g и Hibernate 3.0.
Когда я пытаюсь загрузить нагрузку на сервлет для нагрузочного тестирования, я написал следующие два метода, которые просто создают поток и вызывают синхронный метод, но без какой-либо стековой трассировки журнала My Process в терминах Eclipse.
Я не знаю причину сбоя, если я создаю 500 потоков, то он падает на 487, а если я создаю 1000 потоков, то он падает на 874. Я не знаю, какова реальная причина. Я настроил StuckThreadDetectionValve для обнаружения долго работающих потоков.
/questions/42386600/tajm-aut-zaprosa-tomcat/42386626#42386626
Я поделюсь всеми обновлениями здесь. Пожалуйста, дайте мне подсказку, по крайней мере, если вы знаете, что может быть не так.
** Оба кода дают одинаковый сбой **
Код 1:
public class TokenTest {
static int count = 0;
public static void main(String[] args) {
try {
System.out.println("Start " + new Date());
final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class);
final int max = 50;
ExecutorService executor = Executors.newFixedThreadPool(max);
for (int i = 1; i <= max; i++) {
executor.execute(new Runnable() {
public void run() {
try {
System.out.print(++count +",");
app.verifyToken("7056451004350030976"); //Network Synchronous Operation, calls a Servlet that is deployed in another Server Machine, Using Tomcat 7.0
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
executor.shutdown();
while (!executor.isShutdown()) {
System.out.println("END " + new Date());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Код 2:
public class TokenTest {
static int count = 0;
public static void main(String[] args) {
try {
System.out.println(new Date());
final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class);
final int max=250;
for (int i = 1; i <= max; i++) {
Thread t = new Thread() {
public void run() {
app.verifyToken("7056451004350030976");//Network Synchronous Operation
System.out.print(count++);
System.out.print(", ");
if (count >= max)
System.out.println("\n" + new Date());
}
};
t.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Примечание. Сервер размещен на другом 64-разрядном компьютере под управлением Windows Server 2003.
Обновленный Он просто завершает мой Java-процесс в Eclipse, и если я даю значение, например 5000, то он зависает на 2800, и ничего не происходит, и он не завершает мой процесс. Вот снимок консоли.
Обновление * Спасибо С.Явари. Он привел в правильном направлении. После настройки Stuck_Thread_Detection_Valve на Tomcat и прерывания потоков, которые Stuck Threads
Я могу генерировать нагрузку 500K клиентов на сервере без каких-либо проблем, а также дает сон 100 miliseconds
перед началом нового запроса.
Ниже приведен код:
public class StageOne {
final ApplicationServiceClient appClient = WSClient.getClient(Main.url, ApplicationServiceClient.class);
final SecureWebServiceClient secureClient = WSClient.getClient(Main.url, SecureWebServiceClient.class);
final static List<Long> times = new Vector<Long>();
String token = "";
public String authenticateClient() {
token = appClient.authenticateClient("az_y", "az", "0");
// System.out.println("Registration Response: " + token);
return token;
}
private void getDefaultDepartmentName() {
String deptname = appClient.getDefaultDepartmentName();
// System.out.println("Department: " + deptname);
}
private void getLocation() {
List<String> location = appClient.listLocation();
// System.out.println("Location: " + location);
}
private void registerClient_() {
secureClient.setToken(token);
String respon = secureClient.registerClient("Buddy AZ", "443", "njuy", "1");
// System.out.println(respon);
}
static int count = 0;
public static void main(String[] args) {
int pool = 500000;
final ExecutorService execotors = Executors.newFixedThreadPool(pool);
for (int i = 0; i < pool; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
execotors.execute(new Runnable() {
@Override
public void run() {
long startTime = System.nanoTime();
StageOne one = new StageOne();
one.authenticateClient();
one.getDefaultDepartmentName();
one.getLocation();
one.registerClient_();
long EndTime = System.nanoTime();
// System.out.println("Time in Seconds ("+ (++count) +")" + TimeUnit.NANOSECONDS.toSeconds(EndTime - startTime));
times.add(TimeUnit.NANOSECONDS.toSeconds(EndTime - startTime));
}
});
}
execotors.shutdown();
while (!execotors.isShutdown()) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
}
Collections.sort(times);
long sum = 0;
for (int i = 0; i < times.size(); i++) {
sum += times.get(i);
}
long result = sum / Math.max(1, times.size());
System.out.println("Min Response Time: " + times.get(0));
System.out.println("Average Response Time: " + result);
System.out.println("Max Response Time: " + times.get(times.size() - 1));
}
}
2 ответа
Я думаю, что это просто проблема с потоками. Используйте этот код:
public class Test2 {
public static final Object LOCK = new Object();
static int count = 0;
public static void main(String[] args) {
try {
System.out.println(new Date());
final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class);
final int max=250;
for (int i = 1; i <= max; i++) {
Thread t = new Thread() {
public void run() {
synchronized (LOCK) {
app.verifyToken("7056451004350030976");
}
System.out.print(count++);
System.out.print(", ");
if (count >= max)
System.out.println("\n" + new Date());
}
};
t.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Этот метод (verifyToken
) должен быть потокобезопасным, иначе у вас будет очень много проблем с использованием этого метода внутри потоков.
В коде 1 код не падает. Он работает как задумано. Кажется, с этим кодом проблем нет.