JavaEE——No.2 多线程案例

JavaEE传送门

JavaEE

JavaEE——No.2 线程安全问题

JavaEE——No.1 多线程案例



多线程案例

1. 定时器

定时器, 类似于一个 "闹钟". 代码中的定时器, 通常都是设定 “多长时间之后, 执行某个动作”.

例如: 客户端发送请求之后, 就需要等待服务器响应. 如果服务器一直不响应, 客户端也不能一直死等下去. 客户端经常会设置一个超时时间, 这时就可以使用定时器来实现.

标准库中的定时器

  • 标准库中提供了一个 Timer 类. Timer 类的核心方法为 schedule.

  • schedule 包含两个参数. 第一个参数指定即将要执行的任务代码, 第二个参数指定多长时间之后

    执行 (单位为毫秒).

public class Test {
   
    public static void main(String[] args) {
   
        //标准库的计时器
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
   
            @Override
            public void run() {
   
                System.out.println("7:00了,该起床了");
            }
        },3000);

        timer.schedule(new TimerTask() {
   
            @Override
            public void run() {
   
                System.out.println("9:00了,该起床了");
            }
        },5000);

        timer.schedule(new TimerTask() {
   
            @Override
            public void run() {
   
                System.out.println("8:00了,该起床了");
            }
        },4000);

        System.out.println("闹钟响了!!");
    }
}

这时我们运行代码, 我们发现, 按照时间执行完上述任务之后, 进程并没有退出. Timer 内部需要一组线程来执行注册的任务, 而这里的线程是 前台线程, 会影响进程退出.


定时器的实现

  • schedule 的第一个参数是一个任务, 我们需要能够描述这个任务. (任务包含两方面信息, 需要执行的工作, 与他开始执行的时间)
class MyTask implements Comparable<MyTask>{
   
    //要执行的任务
    private Runnable runnable;
    //什么时间来执行任务(一个时间戳)
    private long time;

    public MyTask(Runnable runnable, long dalay) {
   
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + dalay;
    }

    public Runnable getRunnable() {
   
        return runnable;
    }

    public long getTime() {
   
        return time;
    }

    //实现 Comparable 接口, 便于下文 优先级队列的比较
    @Override
    public int compareTo(MyTask o) {
   
        return (int)(this.time - o.time);
    }
}
  • MyTimer 管理多个任务, 使用优先级阻塞队列 (保证每次取出等待的时间最短的任务, 与线程安全)
class MyTimer {
   
    private BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    public void schedule(Runnable runnable, long after) throws InterruptedException {
   
        MyTask myTask = new MyTask(runnable, after);
		queue.put(MyTask);
    }
}
  • 从队列中去元素, 创建一个单独的扫描线程, 让这个线程不停的来检查队首元素, 时间是否到了, 如果到了则执行该任务
class MyTimer {
   
    
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值