《Java知識應用》Java-線程池(ScheduledExecutorService)


先回顧一下,Runnable 的使用方法。

package demo.knowledgepoints.scheduledtask.run;

/***
* 線程類
*/
public class ThreadTest implements Runnable {

public static int ticket = 9;

@Override
public void run() {
try {
System.out.println("當前線程:"+Thread.currentThread().getName());
while(true){
synchronized (this) {
Thread.sleep(1000L);
if (this.ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName() + ":出售一張票!");
System.out.println("剩余票量:" + ticket);
} else {
System.out.println("沒有票了!");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

 

package demo.knowledgepoints.scheduledtask.run;

public class ThreadMemo {
    public static void main(String[] args) {
        ThreadTest threadTest1 =new ThreadTest();
        new Thread(threadTest1).start();
        new Thread(threadTest1).start();
    }
}

每一個線程的啟動,都會占用資源,一個線程5分鍾執行一次,一個線程10分鍾執行。兩個線程分別啟動則需要啟動兩個線程。線程越多需要啟動的線程就越多。性能浪費就越大。

於是我們會考慮,5分鍾的線程,我們5分鍾到了去喚醒一個線程,執行一次,然后再讓其睡眠,10分鍾的線程也如初,就可以省下同一時間的線程數,線程越多效果越是明顯。

正好:java提供了方法:ScheduledExecutorService

我們就根據ScheduledExecutorService來實現一個線程池:

package demo.knowledgepoints.scheduledtask.inf;

import demo.knowledgepoints.scheduledtask.iml.ScheduledTaskTot;

public interface ScheduledService {

    /**
     * 添加一個任務
     * @author Eric
     * @date 16:14 2019/3/12
     * @params runnable
     * @params taskId
     * @params initialDelay 初次等待 毫秒
     * @params delay 間隔時間 毫秒(不延遲)
     * @throws
     * @return boolean
     **/
    boolean addFixedTask(ScheduledTaskTot scheduledTaskTot);

    /**
     * 添加一個任務
     * @author Eric
     * @date 16:14 2019/3/12
     * @params runnable
     * @params taskId
     * @params initialDelay 初次等待 毫秒
     * @params delay 間隔時間 毫秒(延遲)
     * @throws
     * @return boolean
     **/
    boolean addTask(ScheduledTaskTot scheduledTaskTot);

    /**
     * 修改一個任務
     * @author Eric
     * @date 16:14 2019/3/12
     * @params runnable
     * @params taskId
     * @params initialDelay 初次等待 毫秒
     * @params delay 間隔時間 毫秒
     * @throws
     * @return boolean
     **/
    boolean updateTask(ScheduledTaskTot scheduledTaskTot) throws InterruptedException;

    /**
     * 移除一個任務
     * @author Eric
     * @date 16:14 2019/3/12
     * @params taskId
     * @throws
     * @return boolean
     **/
    boolean remove(String taskId);

    /**
     * 關閉定時任務服務
     * @author Eric
     * @date 16:14 2019/3/12
     * @throws
     * @return void
     **/
    void shutdown();

    /**
     * 初始化定時任務服務
     * @author Eric
     * @date 16:15 2019/3/12
     * @throws
     * @return void
     **/
    void init() throws Exception;
}
package demo.knowledgepoints.scheduledtask.inf;

public interface TaskServcesInf {

    public void Test1();
    public void Test2();
    public void Test3();
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.knowledgepoints.scheduledtask.inf.ScheduledService;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ScheduledServiceIml implements ScheduledService {

    private static ScheduledExecutorService service;


    private static Map<String, ScheduledFuture> futureMap = new ConcurrentHashMap<>();

    @Override
    public boolean addFixedTask(ScheduledTaskTot scheduledTaskTot) {
        if (futureMap.get(scheduledTaskTot.getTaskId()) != null) {
            return false;
        }
        // 這里將任務放入定時服務中
        ScheduledFuture<?> scheduledFuture = service.scheduleAtFixedRate(scheduledTaskTot.getRunnable()
                , scheduledTaskTot.getInitialDelay(), scheduledTaskTot.getDelay(), TimeUnit.MILLISECONDS);

        futureMap.put(scheduledTaskTot.getTaskId(),scheduledFuture);
        return true;
    }

    @Override
    public boolean addTask(ScheduledTaskTot scheduledTaskTot) {
        if (futureMap.get(scheduledTaskTot.getTaskId()) != null) {
            return false;
        }
        // 這里將任務放入定時服務中
        ScheduledFuture<?> scheduledFuture = service.scheduleWithFixedDelay(scheduledTaskTot.getRunnable()
                , scheduledTaskTot.getInitialDelay(), scheduledTaskTot.getDelay(), TimeUnit.MILLISECONDS);

        futureMap.put(scheduledTaskTot.getTaskId(),scheduledFuture);

        return true;
    }

    @Override
    public boolean updateTask(ScheduledTaskTot scheduledTaskTot) throws InterruptedException {
        if (futureMap.get(scheduledTaskTot.getTaskId()) == null) {
            return false;
        }
        // 先停止
        remove(scheduledTaskTot.getTaskId());

        // 再添加
        addTask(scheduledTaskTot);
        return true;
    }

    @Override
    public boolean remove(String taskId) {
        if (futureMap.get(taskId) == null) {
            return false;
        }
        ScheduledFuture scheduledFuture = futureMap.get(taskId);
        scheduledFuture.cancel(false);
        futureMap.remove(taskId);
        return true;
    }

    @Override
    public void shutdown() {
        service.shutdown();
    }

    @Override
    public void init() throws Exception {
        service = Executors.newScheduledThreadPool(8);
    }
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.untils.StringUntil;
import demo.untils.TimeUtil;

import java.lang.reflect.Method;

public class ScheduledTaskTot {

    /** 需要執行方法的線程 */
    Runnable runnable;
    /** 唯一的id用於增刪改 */
    String taskId;
    /** 定時任務需要執行的方法類 */
    String className;
    /** 定時任務需要執行的方法 */
    String method;
    /** 首次執行等待時間 */
    long initialDelay;
    /** 間隔時間 */
    long delay;

    /**
     * 創建一個需要定時的任務
     * @param taskId
     * @param className
     * @param method
     * @param initialDelay
     * @param delay
     * @param beginTime(執行開始時間)
     * @param endTime(執行結束時間)
     */
    public ScheduledTaskTot(String taskId, String className, String method, long initialDelay, long delay, String beginTime, String endTime) {
        this.taskId = taskId;
        this.className = className;
        this.method = method;
        this.initialDelay = initialDelay;
        this.delay = delay;
        // 在創建實例的時候,初始化線程類,通過反射獲取要執行的類與方法,目前沒有加參數,大家可以自行擴展
        runnable = () -> {
            System.out.println("---------------------------------");
            try {
                //在beginTime 到 endTime 之間才執行。
                if(StringUntil.isNotBlank(beginTime) && StringUntil.isNotBlank(endTime)){
                    if(TimeUtil.getTimeMillis(beginTime) - System.currentTimeMillis() >= 0 && TimeUtil.getTimeMillis(endTime) - System.currentTimeMillis() <= 0){
                        Class<?> cls = Class.forName(className);
                        Method method1 = cls.getMethod(method);
                        method1.invoke(cls.newInstance(),null);
                    }
                }else{
                    Class<?> cls = Class.forName(className);
                    Method method1 = cls.getMethod(method);
                    method1.invoke(cls.newInstance(),null);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        };
    }

    public Runnable getRunnable() {
        return runnable;
    }

    public void setRunnable(Runnable runnable) {
        this.runnable = runnable;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public long getInitialDelay() {
        return initialDelay;
    }

    public void setInitialDelay(long initialDelay) {
        this.initialDelay = initialDelay;
    }

    public long getDelay() {
        return delay;
    }

    public void setDelay(long delay) {
        this.delay = delay;
    }
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.knowledgepoints.scheduledtask.inf.TaskServcesInf;

public class TaskServcesIml implements TaskServcesInf {

    public void Test1(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Test1------------------------");
    }
    public void Test2(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Test2------------------------");
    }

    public void Test3(){
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Test3------------------------");
    }
}
package demo.knowledgepoints.scheduledtask.iml;

public class ScheduledServiceTest {

    public static void main(String[] args) {
        ScheduledServiceIml scheduledServiceIml = new ScheduledServiceIml();
        try {
            scheduledServiceIml.init();
            scheduledServiceIml.addTask(new ScheduledTaskTot("T0001","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test1",1000L,5000L,null,null));
            scheduledServiceIml.addTask(new ScheduledTaskTot("T0002","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test2",1000L,5000L,null,null));
            scheduledServiceIml.addTask(new ScheduledTaskTot("T0003","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test3",1000L,5000L,null,null));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 輸出結果:

參考資料:https://blog.csdn.net/money9sun/article/details/88575704?tdsourcetag=s_pctim_aiomsg

如有疑問請留言,每一個都會及時回復。





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM