3

copyIn()別のスレッドでメソッドを呼び出して開始されたコピー処理をキャンセルする方法はありますか?

たとえば、コピーする必要があるcsvファイルのリストがあり、データベースサーバーの能力を最大限に引き出します。そのため、n 個のファイルに対して n 個のスレッド接続を作成しますが、たとえば間違ったファイルが選択された場合などに、単一の操作を中止する方法が見つかりません。

スレッドの強制終了は機能しません - COPY は実行を続けるだけです。

このFutureTask<>クラスはスレッドの作成に使用されるため、スレッドのリストがあります (csv ごとに 1 つ)。

呼び出しtask.cancel(true)は、サーバー上のプロセスのコピーに関しては何もしません。System.exit()火でしか倒せない。

何か案は?

私のコードの一部:

Uploader.java implements Callable

public static long uploadFile(final File file, final String tableName) {

    long status = 0;
    try {
        CopyManager copyManager = 
           new CopyManager((BaseConnection) new DataSource().connect());
        FileReader reader = new FileReader(file);
        status = copyManager.copyIn(sql, reader);
    } catch (SQLException | IOException e) {
       ...
    }
    return status;
}

@Override
public Long call() throws Exception {
    return uploadFile(file, tableName);
}

Upload files method body

for (File file : files) {
        FutureTask<Long> ftask =
                new FutureTask<>(
                        new Uploader(defaultTableName, file)
                );
        tasks.add(ftask);
        execService.execute(ftask);
    }

解決済み:

解決策は見つかりましたが、コードにいくつかの変更が必要でした。

Upload files method body今はこんな感じ

for (File file : files) {
    Uploader uploader = new Uploader(defaultTableName, file);
    uploaders.add(uploader);
    Future<Long> f = execService.submit(uploader);

    //save the Future to get the copy result when finished

}

Uploaderこれにより、データベース接続を閉じて例外を適切に処理できるsome のメソッドを簡単に呼び出すことができます。サーバーでのコピーが停止します。

このソリューションが最も洗練されたものではないかもしれないことは承知していますが、機能し、高速であり、多くのコードは必要ありません。

4

2 に答える 2

1

免責事項: 私はこれを試したことがなく、ソース コードを見てアイデアを得ただけです。

の子孫であるインターフェイスCopyManager.copyIn(String sql)のインスタンスを返すメソッドがあります。そのインターフェースにはメソッドがあります。CopyInCopyOperationcancelCopy()

ここで JavaDocs を参照してください: http://jdbc.postgresql.org/documentation/publicapi/org/postgresql/copy/CopyOperation.html#cancelCopy%28%29

ただし、ストリームを使用してデータをコピーするメソッドは long 値のみを返すため、そこで使用される CopyOperation のインスタンスを使用する方法はありません。

しかし、copyIn() メソッドのソース コードを見ると、これは自分で行うのは非常に簡単に思えます。

したがって、基本的に呼び出す代わりにcopyIn(String, Reader)、コードでそのメソッドのコードを使用します。

// your code 
CopyManager copyManager = 
       new CopyManager((BaseConnection) new DataSource().connect());
FileReader from = ...  // different name!
int bufferSize = 65536;

// here starts the copy of the driver's implementation of the copyIn() method.

char[] cbuf = new char[bufferSize];
int len;

// if you store the instance of the CopyIn interface in an instance variable you 
// should be able to call cancelCopy() on it
CopyIn cp = copyManager.copyIn(sql);  

try {
    while ( (len = from.read(cbuf)) > 0) {
        byte[] buf = encoding.encode(new String(cbuf, 0, len));
        cp.writeToCopy(buf, 0, buf.length);
    }
    return cp.endCopy();
} finally { // see to it that we do not leave the connection locked
    if(cp.isActive())
        cp.cancelCopy();
}
于 2013-09-04T08:02:59.853 に答える