나는 최적화 (메모리) 내 프로그램을 시도하지만, GC는 여전히 지연하고있다

래 가브 :

나는 검사가 프록시 프록시를 사용하여 HTTP 요청을 전송하여 작업하는 경우 것이 자바 소프트웨어의 조각을 작성했습니다.

그런 다음 그들이가 작동하는지 확인을 시도, 데이터베이스에서 30,000 프록시를합니다. 사용되는 데이터베이스에서받은 프록시는 반환 할 ArrayList<String>만 변경 한 Deque<String>아래에 명시된 이유.

프로그램이 작동하는 방법은이 것입니다 ProxyRequest저장 String로서 IP 및 포트가 각각 int로하는 것이 객체. ProxyRequest객체는 방법이 isWorkingProxy()시도가 프록시와 리턴한다 사용하여 요청을 보낼 boolean성공 여부에있다.

ProxyRequest개체는에 의해 감싸되는 RunnableProxyRequest객체 호출이 super.isWorkingProxy()오버라이드의 run()방법. 의 응답을 기반 super.isWorkingProxy()RunnableProxyRequest객체는 MySQL 데이터베이스를 업데이트합니다.

MySQL 데이터베이스의 업데이트가 있습니다를 수행합니다 synchronized().

그것은 FixedThreadPool (A VPS에)를 사용하여 750 개 스레드에서 실행되지만 끝으로, 아주 천천히 (붙어 ~ 50 개 스레드) 분명히 수집기가 작동 쓰레기를 내포된다. 이게 문제 야.

나는 그것이 작동하지 않는 것, 지연을 개선하기 위해 다음을 시도했다 :

1)를 사용하여 Deque<String>프록시 및 사용 Deque.pop()수득 String프록시이다하여. 이 (내가 믿는), 지속적으로하게 Deque<String>GC에 의한 개선해야하는 작은 지연.

2)을 설정 con.setConnectTimeout(this.timeout);하는 경우, this.timeout = 5000;이 방법은, 접속 5 초에서의 결과를 반환한다. 그렇지 않은 경우, 스레드가 완료되고 더 이상 스레드에 활성화 될 수 없습니다.

이 외에도, 나는 성능을 향상시킬 수있는 다른 방법을 알고하지 않습니다.

사람이 나를 GC에 의해 스레드의 끝으로 떨어지고 피하기 / 정지 성능을 향상시킬 수있는 방법을 추천 할 수 있습니까? 나는 이것에 대해 유래 질문 (가 알고있는 자바 스레드 처리의 끝으로 천천히가 ),하지만 난이 질문에 모든 노력을하고 나를 위해 일하지 않았다.

시간 내 주셔서 감사합니다.

코드 조각 :

루프는에 스레드를 추가 FixedThreadPool:

//This code is executed recursively (at the end, main(args) is called again)
//Create the threadpool for requests
//Threads is an argument that is set to 750.
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(threads);
Deque<String> proxies = DB.getProxiesToCheck();

while(proxies.isEmpty() == false) {
    try {
        String[] split = proxies.pop().split(":");

        Runnable[] checks = new Runnable[] {
            //HTTP check
            new RunnableProxyRequest(split[0], split[1], Proxy.Type.HTTP, false),
            //SSL check
            new RunnableProxyRequest(split[0], split[1], Proxy.Type.HTTP, true),
            //SOCKS check
            new RunnableProxyRequest(split[0], split[1], Proxy.Type.SOCKS, false)
            //Add more checks to this list as time goes...
        };

        for(Runnable check : checks) {
            executor.submit(check);
        }

    } catch(IndexOutOfBoundsException e) {
        continue;
    }
}

ProxyRequest 수업:

//Proxy details
private String proxyIp;
private int proxyPort;
private Proxy.Type testingType;

//Request details
private boolean useSsl;

public ProxyRequest(String proxyIp, String proxyPort, Proxy.Type testingType, boolean useSsl) {
    this.proxyIp = proxyIp;
    try {
        this.proxyPort = Integer.parseInt(proxyPort);
    } catch(NumberFormatException e) {
        this.proxyPort = -1;
    }
    this.testingType = testingType;
    this.useSsl = useSsl;
}

public boolean isWorkingProxy() {
    //Case of an invalid proxy
    if(proxyPort == -1) {
        return false;
    }

    HttpURLConnection con = null;

    //Perform checks on URL
    //IF any exception occurs here, the proxy is obviously bad.
    try {
        URL url = new URL(this.getTestingUrl());
        //Create proxy
        Proxy p = new Proxy(this.testingType, new InetSocketAddress(this.proxyIp, this.proxyPort));
        //No redirect
        HttpURLConnection.setFollowRedirects(false);
        //Open connection with proxy
        con = (HttpURLConnection)url.openConnection(p);
        //Set the request method
        con.setRequestMethod("GET");
        //Set max timeout for a request.
        con.setConnectTimeout(this.timeout);
    } catch(MalformedURLException e) {
        System.out.println("The testing URL is bad. Please fix this.");
        return false;
    } catch(Exception e) {
        return false;
    }

    try(
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            ) {

        String inputLine = null; StringBuilder response = new StringBuilder();
        while((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }

        //A valid proxy!
        return con.getResponseCode() > 0;

    } catch(Exception e) {
        return false;
    }
}

RunnableProxyRequest 수업:

public class RunnableProxyRequest extends ProxyRequest implements Runnable {


    public RunnableProxyRequest(String proxyIp, String proxyPort, Proxy.Type testingType, boolean useSsl) {

        super(proxyIp, proxyPort, testingType, useSsl);

    }

    @Override
    public void run() {

        String test = super.getTest();

        if(super.isWorkingProxy()) {

            System.out.println("-- Working proxy: " + super.getProxy() + " | Test: " +  test);

            this.updateDB(true, test);

        } else {
            System.out.println("-- Not working: " + super.getProxy() + " | Test: " +  test);

            this.updateDB(false, test);
        }   


    }

    private void updateDB(boolean success, String testingType) {
        switch(testingType) {
            case "SSL":
                DB.updateSsl(super.getProxyIp(), super.getProxyPort(), success);
                break;
            case "HTTP":
                DB.updateHttp(super.getProxyIp(), super.getProxyPort(), success);
                break;
            case "SOCKS":
                DB.updateSocks(super.getProxyIp(), super.getProxyPort(), success);
                break;
            default:
                break;
        }
    }
}

DB 수업:

//Locker for async 
private static Object locker = new Object();

private static void executeUpdateQuery(String query, String proxy, int port, boolean toSet) {
    synchronized(locker) {
        //Some prepared statements here.
    }
}
래 가브 :

덕분에 피터 Lawrey 솔루션에 저를 안내! :)
그의 코멘트 :

@ILoveKali 내가 네트워크 라이브러리를 찾을 일이 정말 잘못 될 때 연결을 종료 공격적인 충분하지 않습니다했다. 제한 시간은 연결이 잘 일 때 가장 잘 작동하는 경향이있다. YMMV

나는 몇 가지 조사를했다 그래서, 나는 또한 방법을 사용하여주었습니다 setReadTimeout(this.timeout);. 이전에, 난 단지 사용했다 setConnectTimeout(this.timeout);!

이 게시물에 대한 감사 ( HttpURLConnection의 시간 제한 기본값은 다음과 같은 설명) :

불행하게도, 내 경험에서, 서버에 대한 연결과 무슨에 따라 불안정한 상태로 이어질 수있는 이러한 기본값을 사용하여 나타납니다. 당신이 (적어도 읽기) 시간 제한을 HttpURLConnection의 사용하여 명시 적으로 설정하지 않는 경우, 연결은 영구적 오래된 상태로 얻을 수 있습니다. 기본적으로. 그래서 항상 "무엇인가"에 setReadTimeout를 설정하거나 (방법 앱을 실행에 따라 가능한 스레드) 연결을 고아 수 있습니다.

최종 대답은 그래서 : GC가 잘하고 있었다, 그것은 지연에 대한 책임을지지했다. 스레드는 단순히 내가 읽기 시간 제한을 설정하지 않았기 때문에 하나의 숫자에 영원히 갇혀, 그리고 있도록 한 isWorkingProxy()방법 결과를 얻지 독서 유지 않았다.

추천

출처http://43.154.161.224:23101/article/api/json?id=182127&siteId=1