2023.03.14多线程: 自己定义一个线程池,分为任务类,线程类,线程池,测试类。

1.  线程
     线程指的是进程中的一个执行场景,也就是执行流程!进程和线程有什么区别?
     每个进程就是一个应用程序,都会有独立的内存空间
     同一个进程的线程共享其进程中的内存和资源

2.  什么是进程? 
    一个进程就是一个应用程序 ,我们在操作系统每启动一个应用就会启动一个进程。
    例如 QQ 腾讯会议.....

3. 系统引入多进程有什么作用?
   提高CPU的使用频率
   进程和进程之间内存是独立的!!!

4. 什么是线程?
   线程是进程的一个执行场景。一个进程可以启动多个线程!!

5. 进程引入多线程的作用是什么?
    提高进程的使用率
    线程和线程之间栈内存是独立的,堆内存和方法区内存共享,一个线程一个栈!!


6. 描述一下java程序的执行原理:


7. 线程的创建和启动
   1.继承Thread类
   2.实现 Runnable接口
 

 1.继承Thread类

public class ThreadTest extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("我喜欢...");
        }
    }
}


public class Test {
    public static void main(String[] args) {
        ThreadTest threadTest=new ThreadTest();
        threadTest.start();
        Runnable r1=new RunnableTest();
        Runnable r2=new RunnableTest2();
        Thread t1=new Thread(r1);
        Thread t2=new Thread(r2);
        t1.start();
        t2.start();
    }
}


   2.实现 Runnable接口

public class RunnableTest implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("我不喜欢");
        }
    }
}


public class Test {
    public static void main(String[] args) {
        ThreadTest threadTest=new ThreadTest();
        threadTest.start();
        Runnable r1=new RunnableTest();
        Runnable r2=new RunnableTest2();
        Thread t1=new Thread(r1);
        Thread t2=new Thread(r2);
        t1.start();
        t2.start();
    }
}
* @ClassName MyTask
 * @description: 这个是任务类,实现类Runnable 包含任务编号 id  每一个任务执行时间设计为0.2秒
 * @datetime 2023年 03月 14日 11:20
 * @version: 1.0*/ 
public class MyTask implements Runnable{
    private int id;
    public MyTask(int id) {
        this.id = id;
    }
    @Override
    public void run() {
      String name=Thread.currentThread().getName();
        System.out.println("线程"+name+"即将完成任务"+id);
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程"+name+"完成了任务"+id);
    }
    @Override
    public String toString() {
        return "MyTask{" +
                "id=" + id +
                '}';
    }
}
/**
 * @ClassName MyWork
 * @description: 线程类  需要继承 Thread 类
 *  *            一个属性保存线程名字,
 *  *            一个集合 保存所有的任务
 * @datetime 2023年 03月 14日 11:28
 * @version: 1.0
 */
public class MyWork extends Thread{
    private String name;
    private List<Runnable> tasks;//后续任务放到这个集合里面;
    public MyWork(String name, List<Runnable> tasks) {
        super(name);
        this.tasks = tasks;
    }
    @Override
    public void run() {
        while(tasks.size()>0){
            Runnable r=tasks.remove(0);
            r.run();
        }
    }
}
/**
 * @author
 * @ClassName MyThreadPool
 * @description:  *    自定义线程池类
 *  *     成员变量:
 *  *      任务队列  集合   为了安全创建方式不一样
 *  *      核心线程数
 *  *      当前线程数
 *  *      最大线程数
 *  *      任务队列长度
 *  *
 *  *      成员方法
 *  *        提交任务
 *  *           将任务添加到集合中,需要判断是否超出了任务总长度
 *  *        执行任务
 *  *          判断当前线程数量,决定创建核心线程还是非核心线程
 * @datetime 2023年 03月 14日 11:41
 * @version: 1.0
 */
public class MyThreadPool {
    //1.任务队列  集合  需要控制线程安全
   private List<Runnable> tasks=Collections.synchronizedList(new ArrayList<>());
    // 2.当前线程的数量
    private int num;
    //3.核心线程数量
    private int corePoolSize;
    //4. 最大线程数
    private int maxSize;
    //5. 任务队列的长度
    private int worksize;

    public MyThreadPool(int corePoolSize, int maxSize, int worksize) {
        this.corePoolSize = corePoolSize;
        this.maxSize = maxSize;
        this.worksize = worksize;
    }
    public void submit(Runnable r){
        if(tasks.size()>=worksize){
            System.out.println("任务"+r+"被丢弃了");
        }else {
            tasks.add(r);
            exexTask(r);//执行任务
        }
    }
    public void exexTask(Runnable r){
        if(num<corePoolSize){
            new MyWork("核心线程"+num,tasks).start();
            num++;
       }else if(num<maxSize){
            new MyWork("非核心线程"+num,tasks).start();
            num++;
        }else {
            System.out.println("任务"+r+"被缓存了");
}}}
 * @author 
 * @ClassName MyTest
 * @description: 测试类
 *  *   创建线程池对象
 *  *      提交多个任务
 * @datetime 2023年 03月 14日 15:16
 * @version: 1.0
 */

public class MyTest {
    public static void main(String[] args) {
        //创建线程池对象
        MyThreadPool myThreadPool=new MyThreadPool(2,4,20);
        //提交多个任务
        for (int i = 0; i < 30; i++) {
            MyTask myTask=new MyTask(i);
            myThreadPool.submit(myTask);
        }
    }
}

 总结:

第一步:先去创建任务类,属性一个id,作为一个任务的标志,也就是实现Runnable接口,重写run方法和toString方法,这样打印任务的时候,就是id,run方法里面去定义一个任务开始的标志,和任务完成的标志,更容易理解。

获取线程名字的语句:     String name=Thread.currentThread().getName();

第二步:创建一个线程类MyThread,当线程池需要几个线程的时候,可以直接

new MyThread(name,List<Runnable>).start。这个线程类首先,要有线程名字属性和任务类的集合属性,用来存储任务的,也要有一个含参数的构造方法,super(name),调用父类的构造方法。重写run方法,里面要去获取任务集合的任务,采用remove方法,然后调用run方法。

第三步:创建一个线程工厂,含有一个含参构造方法和submit方法,一个创建线程的方法。

控制线程集合中任务的数量,当线程集合长度大于任务队列,任务将会被抛弃,否则tasks.add。然后执行exexTask,标记一个num,当第一个任务进来,创建线程,将tasks的引用地址传给线程类。这个exexTask会去判断任务的状态。

第四步:创建测试类,创建实例对象线程池,模拟任务,submit提交任务。

思考:明明任务被缓存了,后续线程还是能执行这些被缓存的任务呢?

主线程一直在执行tasks.add的操作,

等主线程执行完后,核心线程和非核心线程才会去运行,这个时候,MyWork里面的tasks.remove的指向的内存地址其实就是线程池的tasks的内存地址。只要不结束此次运行,他们两个类实际上一直在操作一个tasks。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值