Cómo utilizar la API de java.util.concurrente.El futuro en lugar de crear hilos explícitamente en Java?

Tengo dos subprocesos que se ejecutan puestas paralelamente en un programa de java de la siguiente manera:

// Threading
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            gpTableCount   = getGpTableCount();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}).start();

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            hiveTableCount = getHiveTableCount();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

while(!(gpTableCount != null && gpTableCount.size() > 0 && hiveTableCount != null && hiveTableCount.size() > 0)) {
    Thread.sleep(5000);
}
// Threading

Ambos tienen la misma funcionalidad. A continuación está el código de getHiveTableCount(). El otro método es ligeramente diferente (una o dos líneas) de la por debajo de uno, pero la funcionalidad sigue siendo la misma.

public Map<String, String> getHiveTableCount() throws IOException, SQLException {
    hiveDataMap     = new HashMap<String, String>();
    hiveTableErrs   = new HashMap<String, String>();
    Iterator<String> hiveIterator = filteredList.iterator();
    Connection hiveConnection = DbManager.getHiveConnection();
    PreparedStatement hive_pstmnt = null;
    String hiveExcpnMsg;
    String ssn;
    String hiveMaxUpdTms;
    Long hiveCount;
    String gpHiveRec;
    String[] hiveArray;
    String[] hiveDetails;
    String hiveQuery;
    while(hiveIterator.hasNext()) {
        gpHiveRec   = hiveIterator.next();      
        hiveArray   = gpHiveRec.split(",");     
        hiveDetails = hiveArray[1].split("\\.");
        hiveQuery   = "select '" + hiveDetails[1] + "' as TableName, count(*) as Count, source_system_name, max(xx_last_update_tms) from " + hiveArray[1] + " where source_system_name='" + hiveArray[2] + "' group by source_system_name";
        try {
            hive_pstmnt             = hiveConnection.prepareStatement(hiveQuery);
            ResultSet hiveCountRs   = hive_pstmnt.executeQuery();
            while(hiveCountRs.next()) {
                hiveCount     = hiveCountRs.getLong(2);
                ssn           = hiveCountRs.getString(3);
                hiveMaxUpdTms = hiveCountRs.getTimestamp(4).toString();
                hiveDataMap.put(hiveDetails[1] + "," + ssn, hiveCount + "," + hiveMaxUpdTms);
            }
        } catch(org.postgresql.util.PSQLException e) {
            hiveExcpnMsg = e.getMessage();
            hiveTableErrs.put(hiveDetails[1] + ": for the SSN: " + hiveArray[2], hiveExcpnMsg + "\n");
        } catch(SQLException e) {
            hiveExcpnMsg = e.getMessage();
            hiveTableErrs.put(hiveDetails[1] + ": for the SSN: " + hiveArray[2], hiveExcpnMsg + "\n");
        } catch(Exception e) {
            hiveExcpnMsg = e.getMessage();
            hiveTableErrs.put(hiveDetails[1] + ": for the SSN: " + hiveArray[2], hiveExcpnMsg + "\n");
        }
    }
    return hiveDataMap;
}

Estos dos subprocesos que se ejecutan simultáneamente. Recientemente he leído en línea que:

El futuro de la clase representa un resultado futuro de una asincronía en el cálculo – un resultado que eventualmente aparezcan en el Futuro después de la el proceso es completo.

Entendí el concepto theoritically pero no sé cómo aplicar el java.util.concurrente.El futuro de la api para el mismo código de arriba en lugar de crear hilos de forma explícita. Podría alguien decirme como puedo implementar multi threading en los métodos: getGpTableCount() & getHiveTableCount usando java.util.concurrente.El futuro de la api en lugar de crear los hilos de la creación de nuevos hilos como new Thread(new Runnable() ?

1 Respuestas

  • Shmulik Klein
    4 de mayo de 2019

    Usted está enviando sus tareas utilizando el Runnable interfaz que no permite que los hilos para devolver un valor al final de la computación (y causan a utilizar una variable compartida - gpTableCount y hiveTableCount).

    El Callable interfaz es una adición posterior que permiten a sus tareas para devolver un valor (en su caso, Map<String, String>).

    Como una alternativa para el trabajo con hilos directamente, La Simultaneidad de la API introduce el ExecutorService como un mayor nivel de objeto que maneja los hilos de piscinas y capaz de ejecutar tareas de forma asíncrona.

    Cuando se debe enviar una tarea de tipo Callable a ExecutorService usted está esperando que la tarea de producir un valor, pero desde la introduccíon punto y el final de computaion no están acoplados, el ExecutorService volverá Future, que le permiten obtener este valor, y el bloque, si este valor no está disponible. Por lo tanto, Future se puede utilizar para sincronizar entre sus diferentes hilos.

    Como una alternativa a ExecutorService también puede echar un vistazo a FutureTask<V> que es la aplicación de RunnableFuture<V>:

    Esta clase proporciona una implementación de base de Future, con métodos para iniciar y cancelar un cálculo, consulta a ver si el cálculo es completo, y recuperar el resultado de la computación

    Un FutureTask puede ser usado para envolver un Callable o Ejecutables objeto.