Browse Source

上传图片,改用多线程,解决速度慢的问题

LiTaohong 6 years ago
parent
commit
1b36adf23f

+ 9 - 0
business/base-service/src/main/java/com/yihu/jw/file_upload/FileUploadCallback.java

@ -0,0 +1,9 @@
package com.yihu.jw.file_upload;
/**
 * 文件上传后的回调
 */
public interface FileUploadCallback {
    void callback(String photoUrl);
}

+ 100 - 0
business/base-service/src/main/java/com/yihu/jw/file_upload/FileUploadRunnable.java

@ -0,0 +1,100 @@
package com.yihu.jw.file_upload;
import com.yihu.jw.restmodel.iot.common.UploadVO;
import com.yihu.jw.util.date.DateUtil;
import org.csource.common.MyException;
import org.springframework.util.Assert;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Random;
import java.util.Set;
/**
 * 多线程处理文件上传,有返回值的多线程
 */
public class FileUploadRunnable implements Runnable {
    /**
     * 上传文件模板类
     */
    private UploadVO uploadVO;
    /**
     * 微信文件流id,从微信把文件下载下来
     */
    private Set<String> wxMediaIdSet;
    private FileUploadService fileUploadService;
    private String  fastdfsUrl;
    private FileUploadCallback callback;
    /**
     * 微信文件流id,从微信把文件下载下来
     */
    private String accessToken;
    public FileUploadRunnable(Set<String> wxMediaIdSet, String accessToken, FileUploadService fileUploadService, String fastdfsUrl, FileUploadCallback callback){
        this.wxMediaIdSet = wxMediaIdSet;
        this.accessToken = accessToken;
        this.fileUploadService = fileUploadService;
        this.fastdfsUrl = fastdfsUrl;
        this.callback = callback;
    }
    @Override
    public void run() {
        Assert.notNull(wxMediaIdSet,"微信文件流id不可为空!");
        StringBuilder photoUrl = new StringBuilder();
        wxMediaIdSet.forEach( one -> {
            InputStream inputStream = getInputStream(one);
            // 重命名文件
            String newFileName = DateUtil.dateToStr(new Date(), DateUtil.YYYYMMDDHHMMSS) + "_" + new Random().nextInt(1000) + ".png";
            try {
                UploadVO uploadVO = fileUploadService.uploadImg(inputStream,newFileName,0,fastdfsUrl);
                photoUrl.append(uploadVO.getFullUrl()).append(",");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
        });
        callback.callback(photoUrl.toString());
    }
    /**
     * 下载多媒体文件(请注意,视频文件不支持下载,调用该接口需http协议)
     *
     * @return
     */
    public InputStream getInputStream(String mediaId) {
        InputStream is = null;
        String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + mediaId;
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
            System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
            http.connect();
            // 获取文件转化为byte流
            is = http.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return is;
    }
}

+ 1 - 1
business/base-service/src/main/java/com/yihu/jw/patient/dao/BasePatientDao.java

@ -26,7 +26,7 @@ public interface BasePatientDao extends PagingAndSortingRepository<BasePatientDO
    @Query("select id as id,idcard as idcard,name as name,case sex when 1 then '男' when 2 then '女' else '未知' end as sex,mobile as phone,committeeName as committeeName,concat(provinceName,cityName,townName,streetName) as address from BasePatientDO")
    List<Map<String,Object>> findBaseInfo(Pageable pageable);
    boolean existsByIdcardAndIdNot(String idcard,String id);
    boolean existsByIdcardAndIdNotAndDel(String idcard,String id,String del);
    boolean existsByIdcardAndDel(String idcard,String del);

+ 18 - 0
business/base-service/src/main/java/com/yihu/jw/patient/dao/BasePatientMedicareCardDao.java

@ -23,4 +23,22 @@ public interface BasePatientMedicareCardDao extends PagingAndSortingRepository<P
    PatientMedicareCardDO findByTypeAndPatientCodeAndDel(String Type,String patientCode,String del);
    boolean existsByCodeAndDel(String code,String del);
    /**
     * 校验就诊卡号是否存在,就诊卡号有机构code,每个机构的就诊卡相互独立
     * @param code
     * @param orgCode
     * @param del
     * @return
     */
    boolean existsByCodeAndOrgCodeAndDel(String code,String orgCode,String del);
    /**
     * 一个居民在一家医院(机构)只能有一张就诊卡
     * @param patientCode
     * @param orgCode
     * @param del
     * @return
     */
    boolean existsByPatientCodeAndOrgCodeAndDel(String patientCode,String orgCode,String del);
}

+ 11 - 0
common/common-exception/src/main/java/com/yihu/jw/exception/business/patient/PatientCardAlreadyExistException.java

@ -0,0 +1,11 @@
package com.yihu.jw.exception.business.patient;
/**
 * 居民卡包卡号已存在
 */
public class PatientCardAlreadyExistException extends RuntimeException{
    public PatientCardAlreadyExistException(String msg){
        super(msg);
    }
}

+ 11 - 0
common/common-exception/src/main/java/com/yihu/jw/exception/business/patient/PatientCardFormatInvalidException.java

@ -0,0 +1,11 @@
package com.yihu.jw.exception.business.patient;
/**
 * 居民卡包卡号格式不正确
 */
public class PatientCardFormatInvalidException extends RuntimeException{
    public PatientCardFormatInvalidException(String msg){
        super(msg);
    }
}

+ 1 - 0
common/common-request-mapping/src/main/java/com/yihu/jw/rm/base/BaseRequestMapping.java

@ -493,6 +493,7 @@ public class BaseRequestMapping {
        public static final String cardOrgList  = "/cardOrgList";
        public static final String sortProList  = "/sortProList";
        public static final String sortCityList  = "/sortCityList";
        public static final String isCardExist  = "/isCardExist";
    }

+ 6 - 1
svr/svr-patient/pom.xml

@ -205,7 +205,12 @@
            <artifactId>junit-platform-commons</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--缩略图-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>
    </dependencies>
    <build>

+ 9 - 2
svr/svr-patient/src/main/java/com/yihu/jw/patient/endpoint/personal_info/PatientMedicareCardEndpoint.java

@ -131,7 +131,7 @@ public class PatientMedicareCardEndpoint extends EnvelopRestEndpoint {
    @GetMapping(value = BaseRequestMapping.PatientMedicareCard.cardOrgList)
    @ApiOperation(value = "获取可绑定卡的医院字母A-Z排序")
    public Envelop cardOrglist(@ApiParam(name = "saasid", value = "租户id")
                                   @RequestParam(value = "saasid", required = false) String saasid) throws Exception {
                               @RequestParam(value = "saasid", required = false) String saasid) throws Exception {
        JSONObject orgObj = patientMedicareCardService.queryOrgSortedList(saasid);
        return success(orgObj);
    }
@ -146,9 +146,16 @@ public class PatientMedicareCardEndpoint extends EnvelopRestEndpoint {
    @GetMapping(value = BaseRequestMapping.PatientMedicareCard.sortCityList)
    @ApiOperation(value = "获取(某省份下)城市字母A-Z排序,不传省份取所有城市")
    public Envelop sortCitylist(@ApiParam(name = "provinceCode", value = "省份代码")
                                   @RequestParam(value = "provinceCode", required = false) String provinceCode) throws Exception {
                                @RequestParam(value = "provinceCode", required = false) String provinceCode) throws Exception {
        JSONObject orgObj = patientMedicareCardService.queryCitySortedList(provinceCode);
        return success(orgObj);
    }
    @GetMapping(value = BaseRequestMapping.PatientMedicareCard.isCardExist)
    @ApiOperation(value = "判断除就诊卡以外的卡号是否存在,false-不存在,true-已存在")
    public Envelop isCardExist(@ApiParam(name = "cardNumber", value = "卡号")
                               @RequestParam(value = "cardNumber", required = true) String cardNumber) throws Exception {
        return success(patientMedicareCardService.isCardExist(cardNumber));
    }
}

+ 54 - 6
svr/svr-patient/src/main/java/com/yihu/jw/patient/service/personal_Info/PatientMedicareCardService.java

@ -1,28 +1,29 @@
package com.yihu.jw.patient.service.personal_Info;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yihu.jw.entity.base.patient.BasePatientFamilyMemberDO;
import com.yihu.jw.entity.base.patient.PatientMedicareCardDO;
import com.yihu.jw.exception.business.patient.PatientCardAlreadyExistException;
import com.yihu.jw.exception.business.patient.PatientCardFormatInvalidException;
import com.yihu.jw.exception.business.patient.PatientCardNotFoundException;
import com.yihu.jw.exception.business.patient.PatientNotFoundException;
import com.yihu.jw.patient.dao.BasePatientMedicareCardDao;
import com.yihu.jw.patient.service.BasePatientMedicardCardService;
import com.yihu.jw.patient.util.JavaBeanUtils;
import com.yihu.jw.patient.util.PinYinUtil;
import netscape.javascript.JSObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@ -42,6 +43,22 @@ public class PatientMedicareCardService extends BasePatientMedicardCardService<P
    @Autowired
    private JdbcTemplate jdbcTemplate;
    /**
     * 校验卡号是否正确,长度不小于6并且只支持数字、字母、下划线
     * @param cardNumber
     * @return
     */
    public void checkCardNumber(String cardNumber){
        Assert.notNull(cardNumber,"卡号不可为空!");
        Assert.state(cardNumber.length() > 6,"卡号长度不能小于6位数!");
        String regex = "^\\w+";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(cardNumber);
        if (!matcher.matches()) {
            throw new RuntimeException("卡号格式不正确,请输入数字或数字与字母的组合!");
        }
    }
    /**
     * 绑定医保卡,需要密码
     *
@ -53,8 +70,8 @@ public class PatientMedicareCardService extends BasePatientMedicardCardService<P
    public void bindMedicareCard(String patientCode, String idcard,String medicareCardNumber,String cityCode) {
        Assert.notNull(patientCode,"居民code不可为空!");
        Assert.notNull(idcard,"身份证号不可为空!");
        Assert.notNull(medicareCardNumber,"医(社)保卡号不可为空!");
        Assert.notNull(medicareCardNumber,"城市code不可为空!");
        checkCardNumber(medicareCardNumber);
        PatientMedicareCardDO card = makeCardInfo(patientCode,idcard,medicareCardNumber);
        card.setParentType(PatientMedicareCardDO.ParentType.CareCard.getType());
        card.setType(PatientMedicareCardDO.Type.MedicareCard.getType());
@ -75,6 +92,7 @@ public class PatientMedicareCardService extends BasePatientMedicardCardService<P
    /**
     * 绑定就诊卡,需要机构和备注
     * 同一个医院同一个居民只能存在一张就诊卡。
     *
     * @param patientCode
     * @param idcard
@ -84,7 +102,17 @@ public class PatientMedicareCardService extends BasePatientMedicardCardService<P
    public void bindPatientIDCard(String patientCode, String idcard,String medicareCardNumber,String orgCode,String remark) {
        Assert.notNull(patientCode,"居民code不可为空!");
        Assert.notNull(idcard,"身份证号不可为空!");
        Assert.notNull(medicareCardNumber,"就诊卡号不可为空!");
        // 校验卡号格式
        checkCardNumber(medicareCardNumber);
        // 校验就诊卡号是否存在
        boolean exist = basePatientMedicareCardDao.existsByCodeAndOrgCodeAndDel(medicareCardNumber,orgCode,"1");
        if(exist){
            throw new PatientCardAlreadyExistException("当前医院就诊卡号已存在,请更改!");
        }
        boolean isOneCardOnly = basePatientMedicareCardDao.existsByPatientCodeAndOrgCodeAndDel(patientCode,orgCode,"1");
        if(isOneCardOnly){
            throw new PatientCardAlreadyExistException("同一家医院一个居民只能拥有一张就诊卡,请更改!");
        }
        PatientMedicareCardDO card = makeCardInfo(patientCode,idcard,medicareCardNumber);
        card.setParentType(PatientMedicareCardDO.ParentType.CareCard.getType());
        card.setType(PatientMedicareCardDO.Type.PatientIDCard.getType());
@ -221,4 +249,24 @@ public class PatientMedicareCardService extends BasePatientMedicardCardService<P
        result.put("sorted", PinYinUtil.pingYinSortReturnJSON(citylist));
        return result;
    }
    /**
     * 判断卡号是否存在,就诊卡除外
     * @param card
     * @return
     */
    public boolean isCardExist(String card){
        Assert.notNull(card,"卡号不可为空!");
        String sql = "SELECT " +
                " count(id) " +
                " FROM " +
                " patient_medicare_card " +
                " WHERE " +
                " !(parent_type = '"+PatientMedicareCardDO.ParentType.CareCard.getType()+"' AND type = '"+ PatientMedicareCardDO.Type.PatientIDCard.getType() +"') and code = '"+ card + "'";
        Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
        if(count > 0){
            return true;
        }
        return false;
    }
}

+ 1 - 1
svr/svr-patient/src/main/java/com/yihu/jw/patient/service/personal_Info/PatientService.java

@ -289,7 +289,7 @@ public class PatientService extends BasePatientService<BasePatientDO, BasePatien
    public boolean existsByIdcard(String idcard, String id) {
        Preconditions.checkNotNull(idcard, "身份证不可为空");
        Preconditions.checkNotNull(id, "id不可为空");
        return basePatientDao.existsByIdcardAndIdNot(idcard, id);
        return basePatientDao.existsByIdcardAndIdNotAndDel(idcard, id,"1");
    }
    /**

+ 39 - 27
svr/svr-patient/src/main/java/com/yihu/jw/patient/service/settings/AccountAppealService.java

@ -1,12 +1,11 @@
package com.yihu.jw.patient.service.settings;
import com.yihu.jw.entity.base.patient.AccountAppealDO;
import com.yihu.jw.entity.base.patient.FeedbackDO;
import com.yihu.jw.exception.business.file_upload.FailedUploadFileException;
import com.yihu.jw.file_upload.FileUploadRunnable;
import com.yihu.jw.file_upload.FileUploadCallback;
import com.yihu.jw.file_upload.FileUploadService;
import com.yihu.jw.patient.dao.settings.AccountAppealDao;
import com.yihu.jw.restmodel.base.patient.AccountAppealVO;
import com.yihu.jw.restmodel.iot.common.UploadVO;
import com.yihu.jw.patient.util.threadPool.ThreadPoolUtil;
import com.yihu.mysql.query.BaseJpaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -14,11 +13,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
 * 账号申诉服务service
@ -39,38 +37,52 @@ public class AccountAppealService extends BaseJpaService<AccountAppealDO, Accoun
    @Value("${fastDFS.fastdfs_file_url}")
    private String fastdfsUrl;
    @Autowired
    private ThreadPoolUtil threadPoolUtil;
    @Transactional(rollbackFor = Exception.class)
    public AccountAppealDO create(AccountAppealDO.Type type, String name,String idcard,String content, String mobile, List<MultipartFile> images) {
    public AccountAppealDO create(AccountAppealDO.Type type, String name,String idcard,String content, String mobile, String wxMediaIds,String accessToken) {
        Assert.notNull(type, "申诉类型不可为空");
        Assert.notNull(mobile, "申诉手机号不可为空");
        Assert.notNull(name, "申诉姓名不可为空");
        Assert.notNull(idcard, "申诉证件号不可为空");
        AccountAppealDO accoutAppeal = new AccountAppealDO();
        if (!CollectionUtils.isEmpty(images)) {
            StringBuilder img = new StringBuilder();
            images.forEach(one -> {
                InputStream inputStream = null;
                try {
                    inputStream = one.getInputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String fileName = one.getOriginalFilename();
                try {
                  UploadVO uploadVO = fileUploadService.uploadStream(inputStream, fileName, fastdfsUrl);
                    img.append(uploadVO.getFullUrl()).append(",");
                } catch (Exception e) {
                    throw new FailedUploadFileException("账号申诉证件图片上传失败");
                }
            });
            accoutAppeal.setImg(img.toString());
        }
        accoutAppeal.setType(type.getValue());
        accoutAppeal.setName(name);
        accoutAppeal.setIdcard(idcard);
        accoutAppeal.setContent(content);
        accoutAppeal.setMobile(mobile);
        this.save(accoutAppeal);
        Set<String> mediaIds = new HashSet<>();
        for (String id : wxMediaIds.split(",")) {
            mediaIds.add(id);
        }
        AccountAppealCallback accountAppealCallback = new AccountAppealCallback(accoutAppeal.getId(),this);
        FileUploadRunnable fileUploadRunnable = new FileUploadRunnable(mediaIds, accessToken, fileUploadService, fastdfsUrl,accountAppealCallback);
        threadPoolUtil.execute(fileUploadRunnable);
        return accoutAppeal;
    }
    class AccountAppealCallback implements FileUploadCallback {
        private Integer accountAppealId;
        private AccountAppealService accountAppealService;
        public AccountAppealCallback(Integer accountAppealId,AccountAppealService accountAppealService){
            this.accountAppealId = accountAppealId;
            this.accountAppealService = accountAppealService;
        }
        @Override
        public void callback(String photoUrl) {
            List<AccountAppealDO> accountAppealDOS = accountAppealService.findByField("id",accountAppealId);
            if(CollectionUtils.isEmpty(accountAppealDOS)){
                return;
            }
            accountAppealDOS.get(0).setImg(photoUrl);
            accountAppealService.save(accountAppealDOS.get(0));
        }
    }
}

+ 43 - 28
svr/svr-patient/src/main/java/com/yihu/jw/patient/service/settings/FeedbackService.java

@ -1,11 +1,11 @@
package com.yihu.jw.patient.service.settings;
import com.netflix.discovery.converters.Auto;
import com.yihu.jw.entity.base.patient.FeedbackDO;
import com.yihu.jw.exception.business.file_upload.FailedUploadFileException;
import com.yihu.jw.file_upload.FileUploadRunnable;
import com.yihu.jw.file_upload.FileUploadCallback;
import com.yihu.jw.file_upload.FileUploadService;
import com.yihu.jw.patient.dao.settings.FeedbackDao;
import com.yihu.jw.restmodel.iot.common.UploadVO;
import com.yihu.jw.patient.util.threadPool.ThreadPoolUtil;
import com.yihu.mysql.query.BaseJpaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -13,11 +13,11 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
/**
 * 
@ -40,42 +40,57 @@ public class FeedbackService extends BaseJpaService<FeedbackDO, FeedbackDao> {
    @Value("${fastDFS.fastdfs_file_url}")
    private String fastdfsUrl;
    @Autowired
    private ThreadPoolUtil threadPoolUtil;
    /**
     *
     * @param type
     * @param feedbackContent
     * @param mobile
     * @param images
     * @param wxMediaIds  微信媒体流id,逗号分隔
     */
    @Transactional(rollbackFor = Exception.class)
    public FeedbackDO create(FeedbackDO.Type type, String feedbackContent, String mobile, List<MultipartFile> images){
    public FeedbackDO create(FeedbackDO.Type type, String feedbackContent, String mobile, String wxMediaIds,String accessToken) throws ExecutionException, InterruptedException {
        Assert.notNull(type,"反馈类型不可为空");
        Assert.notNull(feedbackContent,"反馈类型不可为空");
        Assert.notNull(feedbackContent,"反馈内容不可为空");
        Assert.notNull(mobile,"手机号不可为空");
        Assert.notNull(wxMediaIds,"微信媒体流id不可为空");
        FeedbackDO feedback = new FeedbackDO();
        if(!CollectionUtils.isEmpty(images)){
            StringBuilder img = new StringBuilder();
            images.forEach( one -> {
                InputStream inputStream = null;
                try {
                    inputStream  = one.getInputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String fileName = one.getOriginalFilename();
                try {
                    UploadVO uploadVO = fileUploadService.uploadStream(inputStream, fileName, fastdfsUrl);
                    img.append(uploadVO.getFullUrl()).append(",");
                } catch (Exception e) {
                    throw new FailedUploadFileException("上传反馈图片失败");
                }
            });
            feedback.setImg(img.toString());
        }
        feedback.setType(type.getValue());
        feedback.setFeedbackContent(feedbackContent);
        feedback.setMobile(mobile);
        this.save(feedback);
        Set<String> mediaIds = new HashSet<>();
        for (String id : wxMediaIds.split(",")) {
            mediaIds.add(id);
        }
        FeedbackCallback feedbackCallback = new FeedbackCallback(feedback.getId(),this);
        FileUploadRunnable fileUploadRunnable = new FileUploadRunnable(mediaIds, accessToken, fileUploadService, fastdfsUrl,feedbackCallback);
        threadPoolUtil.execute(fileUploadRunnable);
        return feedback;
    }
    class FeedbackCallback implements FileUploadCallback{
        private Integer feedbackId;
        private FeedbackService feedbackService;
        public FeedbackCallback(Integer feedbackId,FeedbackService feedbackService){
            this.feedbackId = feedbackId;
            this.feedbackService = feedbackService;
        }
        @Override
        public void callback(String photoUrl) {
            List<FeedbackDO> feedbackDOs = feedbackService.findByField("id",feedbackId);
            if(CollectionUtils.isEmpty(feedbackDOs)){
                return;
            }
            feedbackDOs.get(0).setImg(photoUrl);
            feedbackService.save(feedbackDOs.get(0));
        }
    }
}

+ 8 - 0
svr/svr-patient/src/main/java/com/yihu/jw/patient/util/threadPool/ThreadPoolUtil.java

@ -1,5 +1,9 @@
package com.yihu.jw.patient.util.threadPool;
import com.yihu.jw.file_upload.FileUploadCallback;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
@ -21,6 +25,10 @@ public class ThreadPoolUtil {
        threadPool.execute(runnable);
    }
    public Future submit(Callable callable) {
        return threadPool.submit(callable);
    }
    public void execute(FutureTask futureTask) {
        threadPool.execute(futureTask);
    }