Java多執行緒之執行緒排程詳解
阿新 • • 發佈:2018-12-18
排程的概念
給定時間結點,時間間隔,任務次數,然後自動執行任務
應用場景舉例
1.日誌清理:每隔三個月,清理公司日誌檔案
2.日誌備份:每個一週,備份公司檔案
3.工資結算:每個月29號,考勤彙報,業務結算,計算工資
排程的實現方式:
- Timer+TimerTask
- ScheduledExecutor
- 開源工具包:Quartz,JcronTab
單執行緒排程
執行排程任務的個數為單個
Timer +TimerTask實現方式:
- Timer實現
Timer是一種工具,執行緒用其安排以後在後臺執行緒中執行的任務。可安排任務執行一次,或者定期重複執行。
主要方法摘要
- TimerTask 方法摘要
入門案例:
import java.util.Timer; import java.util.TimerTask; public class TimerTest { public static void main(String[] args) { Timer timer = new Timer(); //任務在多久以後執行 long delay = 1000;//執行任務前的延遲時間,單位是毫秒。 long period =1000;//執行各後續任務之間的時間間隔,單位是毫秒。 timer.scheduleAtFixedRate(new Task(), delay, period); //task - 所要安排的任務。 } } class Task extends TimerTask{ @Override public void run() { // TODO Auto-generated method stub System.out.println("正在工作"); } }
- TaskList 和TaskThread只有一個
- Timer物件接受任務和時間引數,將任務放到TimerList中,TimerList會按照,Task最初執行時間進行排序
- TimerThread在Timer在被建立時候會成為一個守護執行緒。
- TimerThread會找到最近排程的執行任務,記錄事件後休眠。
- 達到再次執行時間的時候,TimerThread重新執行
- 再一次記錄下一哥即將執行的任務後,休眠
缺點:同一時間,只會有一個任務被排程執行。上一個任務的執行會影響下一個任務的啟動時間。
多執行緒排程
執行排程任務的個數為單個
ScheduledExecutor的實現
- 每一被排程的任務,都可以從執行緒池中,安排一個執行緒來執行。任務併發執行,不受干擾。
- 會將放入的任務跟執行緒池匹配實現繫結
方法摘要 案例:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest {
public static void main(String[] args) {
//實現排程的執行緒池,建立一個有10個執行緒的執行緒池,而且可以實現排程。
ScheduledExecutorService service =Executors.newScheduledThreadPool(10);
//建立任務
ScheduleTask t1 = new ScheduleTask("小李");
ScheduleTask t2 = new ScheduleTask("小王");
long period =1;
long delay=1;
//執行緒池繫結,執行緒會自動將任務給執行緒
service.scheduleAtFixedRate(t1, delay, period,TimeUnit.SECONDS);
service.scheduleAtFixedRate(t2, delay, period,TimeUnit.SECONDS);
/*
* command - 要執行的任務
Delay - 首次執行的延遲時間
period - 連續執行之間的週期
unit - Delay 和 period 引數的時間單位
* */
}
}
class ScheduleTask implements Runnable{
private String Name ;
public ScheduleTask(String name) {
Name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+Name+"正在工作")
}
}
缺點: 如果要精準定位某個時間點(例如:每個月29號,下午14:28分 12秒)去排程,就很複雜。