【Java】マルチスレッド

処理の流れ(使用例)

スレッドの処理が終わるまで待機画面を表示し、
スレッドが完了すれば完了画面に遷移する処理の流れ。

使用方法(Springでの例)

スレッドの実行側

@Controller
public class OfferController {
    @Autowired
    OfferService offerLogic;
    @Autowired
    HttpSession session;

    @RequestMapping(value = "/offer", method = RequestMethod.GET)
    public String home(Model model) {
        OfferForm form = new OfferForm();
        form.setUserId(7);

        // スレッド初期化
        SampleThread thread = new SampleThread(offerLogic, form);
        // スレッド実行
        thread.start();

        // スレッドの処理状況をセッションで受け取れるようにする
        session.setAttribute("threadStatus", thread.getThreadStatus());

        return "offer/confirmThread";
    }

    @RequestMapping(value = "/waitThreadCompleted", method = RequestMethod.POST)
    public String waitThreadCompleted(Model model) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }
        // スレッドの値を取得
        SampleThreadStatusForm statusform = (SampleThreadStatusForm)session.getAttribute("threadStatus");

        // スレッドが終了した場合
        if ("1".equals(statusform.getStatus())) {
            // タイムアウトした場合
            if (statusform.isTimeOutFlg()) {
                return "offer/timeOutThread";
            }
            // 正常に完了した場合
            else {
                return "offer/completeThread";
            }
        }
        // スレッドが終了していない場合(今回の例では通らないがメモ用に記載)
        else {
            // 待機画面に戻る
            return "offer/confirmThread";
        }
    }
}

スレッド内の処理側

public class SampleThread extends Thread {
    // スレッド状態フォーム
    private SampleThreadStatusForm threadStatus = new SampleThreadStatusForm();
    // ビジネスロジック
    private OfferService offerLogic;
    // フォーム
    private OfferForm offerForm;

    public SampleThreadStatusForm getThreadStatus() {
        return threadStatus;
    }
     // コンストラクタ
    public SampleThread (OfferService logic, OfferForm form) {
        this.offerLogic = logic;
        this.offerForm = form;
    }

    // スレッド実行する
    public void run() {
        try {
            // スリープ時間(ミリ秒)
            final long waitMillis = 5000;
            // 最大スリープ時間(ミリ秒)
            final long maxWaitMillis = 30000;
            // スリープ時間合計
            long totalWaitMillis = 0;

            // スレッドの処理状態(0:処理中、1:処理完了)
            threadStatus.setStatus("0");

            do {
                // スリープ
                Thread.sleep(waitMillis);
                // スリープの合計時間を更新
                totalWaitMillis += waitMillis;

                // ビジネスロジックを実行(例としてDB検索を行う)
                MemberBean member = offerLogic.selectMember(offerForm.getUserId());
                // 検索がヒットした場合
                if (member != null) {
                    // 検索結果をスレッド状態フォームに格納して渡す
                    threadStatus.setMember(member);
                    // ループを抜ける
                    break;
                }
            } while (totalWaitMillis < maxWaitMillis);

            // タイムアウトした場合
            if (totalWaitMillis >= maxWaitMillis) {
                // フラグでタイムアウトしたことが分かるようにする
                threadStatus.setTimeOutFlg(true);
            }
        } catch (Exception e) {
        }

        // スレッドの処理状態を処理完了にする
        threadStatus.setStatus("1");
    }
}

待機画面のjsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function action(){
  document.frm.action="waitThreadCompleted";
  document.frm.submit();
}
</script>
</head>
<body onload="action()">
<form:form modelAttribute="offerForm" name="frm">
スレッド処理中
</form:form>
</body>
</html>

スレッドのフォーム

public class SampleThreadStatusForm implements Serializable{
    private static final long serialVersionUID = -4098194215772825545L;

    private String status;
    private MemberBean member;
    private boolean timeOutFlg;

    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public MemberBean getMember() {
        return member;
    }
    public void setMember(MemberBean member) {
        this.member = member;
    }
    public boolean isTimeOutFlg() {
        return timeOutFlg;
    }
    public void setTimeOutFlg(boolean timeOutFlg) {
        this.timeOutFlg = timeOutFlg;
    }
}