JavaEE-线程进阶


在这里插入图片描述在这里插入图片描述
在这里插入图片描述


模拟实现一个定时器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行结果如下:
在这里插入图片描述
上述模拟定时器的全部代码:

import java.util.PriorityQueue;

//创建一个类,用来描述定时器中的一个任务
class MyTimerTask implements Comparable<MyTimerTask> {
    //任务执行时间
    private long time;
    //具体任务
    private Runnable runnable;

    //构造函数
    public MyTimerTask(Runnable runnable,long delay) {
        this.time = System.currentTimeMillis()+delay;
        this.runnable = runnable;
    }
    public long getTime() {
        return time;
    }
    public Runnable getRunnable() {
        return runnable;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        //时间小的任务,会被放置在队首
        return (int)(this.time-o.time);
    }
}

//定时器类的本体
class MyTimer{
    //创建一个优先级队列存储上述的N个任务
    private PriorityQueue<MyTimerTask> queue=new PriorityQueue<>();

    //用来加锁的对象
    private Object locker=new Object();

    //提供一个schedule方法,把要执行的任务添加到队列中去
    public void  schedule(Runnable runnable,long delay){
        //new 一个任务对象
        synchronized (locker){
            MyTimerTask task=new MyTimerTask(runnable,delay);
            queue.offer(task);
            //每次来新的任务,都唤醒之前的扫描线程,让扫描线程根据当前的任务情况,重新规划等待时间
            locker.notify();
        }
    }
    //构造函数 提供一个扫描线程,一方面去监控队首元素是否到执行时间了,另一方面,如果到了执行时间,这需要调用这里的Runable中的run方法来完成任务
    public MyTimer(){
        Thread t=new Thread(() ->{
           while(true){
               try {
                   synchronized (locker){
                       while(queue.isEmpty()){
                           //如果当前队列为空,就不应该去队列中取任务,使用wait进行等待,直到有任务加入队列
                           locker.wait();
                       }
                       //判断当前队列中的队首元素距离执行时间的时间差
                       MyTimerTask task=queue.peek();
                       long curTime=System.currentTimeMillis();
                       if(curTime>=task.getTime()){
                           //当前时间大于等于任务的执行时间,开始执行
                           queue.poll();//把已经执行的任务弹出队列
                           task.getRunnable().run();//执行任务
                       }else{
                           //没有到任务时间,扫描线程休眠时间差
                           //Thread.sleep(task.getTime()-curTime);
                           locker.wait(task.getTime()-curTime);
                       }
                   }
                   }catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        t.start();
    }

}

public class Demo21 {
    public static void main(String[] args) {
        MyTimer timer=new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 3");
            }
        },3000);

        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2");
            }
        },2000);

        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1");
            }
        },1000);
        System.out.println("程序开始运行");
    }
}


线程池
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


模拟实现一个线程池
只需要提交任务给线程池即可
核心操作为 submit, 将任务加入线程池中
使用一个 BlockingQueue 组织所有的任务

代码如下:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

//模拟实现一个线程池
class MyThreadPool{
    //将添加到线程池中的任务可以放置到这个队列中
    private BlockingQueue<Runnable> queue =new LinkedBlockingQueue<>();
    //通过这个方法可以将任务添加到线程池中
    public void  submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
    //构造函数,创建一个线程池,数量为n
    public  MyThreadPool(int n){
        for (int i = 0; i <n; i++) {
            Thread t=new Thread(() ->{
               while(true){
                   try {
                       //取放入线程池队列中的任务进行执行
                       Runnable runnable= queue.take();
                       runnable.run();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            });
            t.start();
        }
    }

}
public class Demo23 {
    public static void main(String[] args) throws InterruptedException {
    MyThreadPool myThreadPool=new MyThreadPool(4);
        for (int i = 0; i <10; i++) {
            myThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(
                            Thread.currentThread().getName()+"hello"
                    );
                }
            });
        }
    }
}

执行结果如下:

在这里插入图片描述

在这里插入图片描述


进阶内容


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
上述第二种情况的案例,如下
在这里插入图片描述
结果如下:
在这里插入图片描述
上述过程的所有代码:

//死锁
public class Demo24 {
    private  static  Object locker1=new Object();
    private  static  Object locker2=new Object();
    public static void main(String[] args) {
        Thread t1=new Thread(() ->{
            synchronized (locker1) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (locker2){
                    System.out.println("t1 两把锁加锁成功");
                }
            }

        });

        Thread t2=new Thread(() ->{
            synchronized (locker2) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (locker1){
                    System.out.println("t2 两把锁加锁成功");
                }
            }

        });

        t1.start();
        t2.start();
    }
}


我们可以通过jconsole来观察线程的执行过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
利用原子类实现线程安全
在这里插入图片描述
上述的代码如下:

import java.util.concurrent.atomic.AtomicInteger;

//利用原子类实现线程安全
public class Demo25 {
    private static AtomicInteger count=new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(() -> {
            for (int i = 0; i <5000; i++) {
                count.getAndIncrement();//后置++

            }
        });
        Thread t2=new Thread(() -> {
            for (int i = 0; i <5000; i++) {
                count.getAndIncrement();//后置++

            }
        });
        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(count.get());
    }
}


在这里插入图片描述

在这里插入图片描述


*加粗样式**


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述
下面利用Callable建立一个线程
在这里插入图片描述
上述过程的代码如下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//利用Callable建立一个线程
public class Demo26 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable =new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum=0;
                for (int i = 0; i <1000; i++) {
                    sum+=i;
                }
                return sum;
            }
        };
        //callable不能直接用,需要借用FutureTask这个标签
        FutureTask<Integer> futureTask=new FutureTask<>(callable);
        Thread t =new Thread(futureTask);
        t.start();

        System.out.println(futureTask.get());
    }
}

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
下面简单使用一下这个信号量
在这里插入图片描述
上述过程的完整代码如下:

import java.util.concurrent.Semaphore;
//Semaphore  信号量
public class Demo27 {
    public static void main(String[] args) throws InterruptedException {
        //指定计数器的初始值
        Semaphore semaphore=new Semaphore(4);
        semaphore.acquire();
        System.out.println("执行了一次P操作");
        semaphore.acquire();
        System.out.println("执行了一次P操作");
        semaphore.acquire();
        System.out.println("执行了一次P操作");
        semaphore.acquire();
        System.out.println("执行了一次P操作");
        semaphore.acquire();
        System.out.println("执行了一次P操作");
    }
}


在这里插入图片描述同时等待 N 个任务执行结束.
在这里插入图片描述
上述过程的完整代码如下:

import java.util.concurrent.CountDownLatch;
//使用CountDownLatch将任务分配给多个线程来完成
public class Demo28 {
    public static void main(String[] args) throws InterruptedException {
        //指定创建任务的数量
        CountDownLatch countDownLatch=new CountDownLatch(10);
        for (int i = 0; i <10; i++) {
            int id=i;
            Thread t=new Thread(() ->{
                System.out.println( id + "开始工作");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println( id + "结束工作");
                // 每个任务执行结束这里, 调用一下方法,记录该线程是否结束
                // 把 10 个线程想象成短跑比赛的 10 个运动员. countDown 就是运动员撞线了.
                countDownLatch.countDown();
            });
            t.start();
        }
        // 主线程中可以使用 countDownLatch 负责等待任务结束.
        // a => all 等待所有任务结束. 当调用 countDown 次数 < 初始设置的次数, await 就会阻塞.
        countDownLatch.await();
        System.out.println("所有任务执行完毕");
    }
}

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值