定时器是软件开发中的一个重要组件.类似于一个"闹钟".达到一个设定的时间之后,就执行某个指定好的代码.
import java.util.Timer;
public class Test {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello timer");
}
},3000);
System.out.println("main");
}
}
package hello;
import java.util.concurrent.PriorityBlockingQueue;
//实现Comparable 接口 用于 插入时比较
class MyTask implements Comparable<MyTask>{
//任务干什么
private Runnable runnable;
//任务什么时候干
private long time;
//delay 是一个时间间隔
public MyTask(Runnable runnable, long delay) {
this.runnable = runnable;
this.time = System.currentTimeMillis()+delay;
}
public void run(){
runnable.run();
}
public long getTime(){
return time;
}
@Override
public int compareTo(MyTask o) {
return (int)(this.time - o.time);
}
}
class MyTimer{
//定时器内部能够存放多个任务
//优先级阻塞堆
private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
public void schedule(Runnable runnable,long delay){
MyTask myTask = new MyTask(runnable, delay);
queue.put(myTask);
//每次添加新的任务时,唤醒线程,再次计算时间
synchronized (locker){
locker.notify();
}
}
private Object locker = new Object();
public MyTimer() {
Thread t = new Thread(()->{
while(true){
try {
//取出队首元素
MyTask task = queue.take();
//比较时间到了没
long curTime = System.currentTimeMillis();
if(curTime < task.getTime()){
//时间没到,放回队列
queue.put(task);
//队首元素为最早执行的任务,阻塞等待队首元素 或者 等待新的任务添加进来后唤醒
//阻塞等待最早的任务执行,防止 一直while(true)循环,无效消耗CPU
synchronized (locker){
locker.wait(task.getTime()-curTime);
}
}else{
//时间到了,执行
task.run();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
public class Test {
public static void main(String[] args) {
MyTimer timer = new MyTimer();
timer.schedule(()->{
System.out.println("hello timer");
},3000);
System.out.println("main");
}
}
线程池的拒绝策略是指当线程池无法接受新的任务时, 如何处理这些被拒绝的任务.
AbortPolicy(默认):直接抛出异常,拒绝任务提交。CallerRunsPolicy:由提交任务的线程来执行该任务,即不会在线程池中执行该任务。DiscardOldestPolicy:丢弃最老的等待任务,即队列中最早提交的任务,然后尝试重新提交任务。DiscardPolicy:直接丢弃该任务,不做任何处理。ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
使用线程池时,需要注意线程池的参数配置,包括核心线程数、最大线程数、任务队列等。同时,也需要根据实际情况选择合适的拒绝策略来保证程序的正确性和稳定性。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 认为内核态效率低,不一定是真的低,而是随着代码进入内核态,就不可控了.内核可能还要做其他的事情
* 内核什么时候把活干完,把结果给你 (有时候快,有时候慢)
*/
class MyThreadPool{
//描述一个任务,直接使用Runnable ,不需要额外创建类
//使用一个数据结构来组织若干任务
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
//描述一个线程,工作线程的功能就是从任务队列中取任务并执行
static class Worker extends Thread{
private BlockingQueue<Runnable> queue = null;
public Worker(BlockingQueue<Runnable> queue){
this.queue = queue;
}
@Override
public void run() {
while(true){
try {
Runnable runnable = queue.take();
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private List<Thread> workers = new ArrayList<>();
public MyThreadPool(int n){
for (int i = 0; i < n; i++) {
Worker worker = new Worker(queue);
worker.start();
workers.add(worker);
}
}
public void submit(Runnable runnable){
try {
queue.put(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
MyThreadPool myThreadPool = new MyThreadPool(10);
for (int i = 0; i < 100; i++) {
myThreadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello threadpool");
}
});
}
}
}