【Java】シングルスレッド処理

Javaのスレッド処理に関するメモ。
JDK1.4ではThreadを利用していたが、JDK1.5以降はExecutorServiceを利用する。

  • 呼び出す側
    public static void main(String[] args) {
        Z_Thread main = new Z_Thread();
        // スレッド管理サービスを生成する。
        ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
        main.executeSingleTask(singleExecutor);
        // スレッドを終了する。
        singleExecutor.shutdown();
    }
    
    private void executeSingleTask(ExecutorService serviceExecutor) {
        // 戻り値を定義する。
        Future<Long> future = null;
        try {
            String fileDir = "D:\\";
            String fileName = "";
            // 指定ディレクトリの「*.txt」の一覧を取得する。
            Path path = Paths.get(fileDir);
            try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path, "*.txt")) {
                // 指定ディレクトリの「*.txt」数分繰り返す。
                for (Path p : directoryStream) {
                    // ファイル名を取得する。
                    fileName = p.getFileName().toString();
                    // 取得したファイル名をタスクに登録する。
                    // タスクはCallableを利用することで戻り値と例外を受け取れるようにする。
                    // タスクはRunnableを利用すると戻り値と例外は受け取れない。
                    future = serviceExecutor.submit(new CallableTest(fileDir, fileName));
                    // Futureクラスのgetメソッドを呼び出すと呼び出し側は結果が返ってくるまで処理を止める。
                    // 20秒を過ぎるとタイム例外が返ってくる。
                    Long result = future.get(20000, TimeUnit.MILLISECONDS);
                    System.out.println("結果:" + result + ":スレッドの結果を受け取りました。");
                }
            }
        } catch (InterruptedException e){
            System.out.println("割り込み例外");
        } catch (ExecutionException e) {
            System.out.println("タスクの中で例外発生");
        } catch (TimeoutException e) {
            System.out.println("タイムアウト例外発生");
        } catch (Exception e) {
            System.out.println("何かの例外発生");
        } finally {
            future.cancel(true);
        }
    }
    
  • 呼び出される側(タスク)(Callableを利用する)
    private String fileDir = "";
    private String fileName = "";
    
    public CallableTest(String fileDir, String fileName) {
        this.fileDir = fileDir;
        this.fileName = fileName;
    }
    
    public Long call() throws Exception {
        try {
            System.out.println(Thread.currentThread().getId() + ":スレッド処理開始");
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("スレッドに割り込みありました。");
                throw new InterruptedException("割り込み例外");
            }
    
            // 何かの処理を想定
            Thread.sleep(10000);
            // コンストラクタで指定したファイルの内容を読み取り表示する。
            List<String> line = Files.readAllLines(Paths.get(fileDir, fileName), Charset.forName("UTF-8"));
            System.out.println(Thread.currentThread().getId() + ":" + fileName + "の内容を表示");
            for (String str : line) {
                System.out.println(str);
            }
        } catch(Exception e){
            System.out.println(Thread.currentThread().getId() + "エラー検知");
            throw e;
        } finally {
            System.out.println(Thread.currentThread().getId() + ":スレッド処理終了");
        }
        return Thread.currentThread().getId();
    }