Java中的线程休眠、定时任务和线程池

Thread.sleep();

阻塞线程休眠,但不释放锁

举例:

static void main() throws InterruptedException {
//        for (int i = 0; i < 10; i++) {
//            Thread.sleep(Duration.ofSeconds(1));
//            //当前线程休眠1秒,阻塞
//            IO.println(i);
//        }

        Thread t1 = new Thread(){
            @Override
            public void run() {
                IO.println("Hello,im thread 1");
                try{
                    Thread.sleep(2000);
                }catch (InterruptedException e){
                    throw new RuntimeException(e);
                }

                IO.println("I'm over");
            }
        };

        t1.start();
    }

另一种写法

//另外一种写法
TimeUnit.SECONDS.sleep(2);

wait和notify

使用wait休眠要使用锁(lock),只能通过锁对象来进行调用,因此只能在同步块或者同步方法中使用,与sleep的区别是wait是释放锁的,也就意味着在此线程阻塞的时候,其他共享同一把锁的线程可以继续执行。

示例如下:新建一个CountTask任务

public class CountTask implements Runnable{
    public byte[] lock = new byte[0];

    @Override
    public void run() {
        synchronized(lock){

            for (int i = 0; i < 10; i++) {
                try {
                    lock.wait(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                IO.println(i);
            }

        }

    }
}

测试类:

public class test02 {
    static void main() {
        CountTask ct = new CountTask();
        Thread t1 = new Thread(ct);
        t1.start();

    }
}

wait有多个重写方法,如果不写入任何参数,则无限期休眠。,示例如下:

修改CountTask任务类:

public class CountTask implements Runnable{
    public byte[] lock = new byte[0];
    public boolean dontWait = false;

    @Override
    public void run() {
        synchronized(lock){

            for (int i = 0; i < 10; i++) {
                try {
                    if(!dontWait){
                        lock.wait();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                IO.println(i);
            }

        }

    }
}

此时若不唤醒,则进程永久阻塞,所以还要添加唤醒条件和唤醒操作,修改测试类:

public class test02 {
    static void main() throws InterruptedException {
        CountTask ct = new CountTask();
        Thread t1 = new Thread(ct);
        t1.start();

        Thread.sleep(2000);
        //休眠2秒之后,将线程唤醒
        synchronized (ct.lock){
            ct.dontWait = true;
            //随机唤醒一个睡眠的线程
            ct.lock.notify();
            //唤醒所有睡眠的线程
            ct.lock.notifyAll();
            
        }

    }
}

此处需要注意,用哪把锁执行的wait,就要用哪把锁唤醒。

定时任务

import java.util.Timer;
import java.util.TimerTask;

public class Test03 {
    static void main() {
        //定时任务
        TimerTask tt = new TimerTask() {//TimerTask是一个内部类
            @Override
            public void run() {
                IO.println("起床学习了");
            }
        };

        //创建一个定时器
        Timer timer = new Timer();
        timer.schedule(tt,3000);

    }
}

线程池

Java 5引⼊线程池。线程池相关类主要有:Executor、ExecutorService、Executors等等。

常见的几种线程池:

//创建一个仅有单个线程的线程池
ExecutorService es1 = Executors.newSingleThreadExecutor();

//创建拥有固定数量限制的线程池
ExecutorService es2 = Executors.newFixedThreadPool(10);

//创建可缓存无限数量线程的线程池
ExecutorService es3 = Executors.newCachedThreadPool();

//创建一个执行定时任务的线程池
ScheduledExecutorService es4 = Executors.newScheduledThreadPool(5);

//JDK25特有的:创建java绿色线程(虚拟线程、协程)的线程池
ExecutorService es5 = Executors.newVirtualThreadPerTaskExecutor();

演示:

es2.submit(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    IO.println(i);
                }
            }
        });

        //close会阻塞,等待所有任务结束后才会关闭线程池
        //es2.close();
        //IO.println("主线程结束");

特别的,定时任务线程池用法:

//定时任务线程池
        ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
        //延迟一段时间执行任务
        ses.schedule(new Runnable() {
            @Override
            public void run() {
                IO.println("起床了");
            }
        },10, TimeUnit.SECONDS);


        ses.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                IO.println("学累了,玩一会");
            }
        },1,3,TimeUnit.SECONDS); //首次延迟1秒,之后每3秒执行一次
        IO.println("主线程结束");
    }

 

THE END
文章版权归Tinsur.cn所有,转载分享请标注原链接
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容