进程与线程

一、并行、并发和串行

并行:两个或者多个事件在同一时刻发生;(不同实体)

并发:两个或多个事件在同一事件间隔发生;(同一个实体)

串行:同一时刻一个CPU只能处理一件事;

二、进程与线程

进程:程序运行和资源分配的基本单位

线程:进程的一个实体,CPU调度和分派的基本单位,同一进程中的多个线程可以并发执行。

三、线程的状态

线程生命周期,五种状态

1、新建状态(new):当线程对象创建后就进入了新建状态,如:Thread t = new Thread();

2、就绪状态(Runnable):当调用线程对象的start()方法,线程即为进入就绪状态。

        处于就绪(可运行)状态的线程,只是说明线程已经做好准备,随时等待CPU调度状态,并不是执行了t.start()此线程立即就会执行。

3、运行状态(Running):当CPU调度了处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态。

        就绪状态是进入运行状态的唯一入口,也就是线程想要进入运行状态,状态执行,先得处于就绪状态。

4、阻塞状态(Blocked):处于状态中的线程由于某种原因,暂时放弃对CPU的使用权。停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行。

三种阻塞状态:

1)等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态。

2)同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),会进入同步阻塞。

3)其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态。           当sleep()状态超时,join()等待线程终止或者超时或者I/O处理完毕时线程重新转让就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

四、多线程创建方式

1、继承Thread类

1)自定义自己的多线程类

2)重写run(),里面是我们自己的业务

3)创建自定义线程类对象

4)通过线程对象 .start(),将线程加入就绪列

5)查看多线程编程的抢占效果

public class TestThread {
    public static void main(String[] args) {
        //4.创建线程对象进行测试
        /*4.new对应的是线程的新建状态*/
        /*5.要想模拟多线程,至少得启动2个线程,如果只启动1个,是单线程程序*/
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
        /*6.这个tun()如果直接这样调用,是没有多线程抢占执行的效果的
        * 只是把业务方法看作是普通方法来调用,谁先写,就先执行谁*/
//        t1.run();
//        t2.run();
//        t3.run();
//        t4.run();
        /*7.start()对应的状态才是线程的就绪状态,它会把刚刚新建好的线程加入到就绪
        * 队列中,至于什么时候执行,就是多线程抢占的效果,需要OS选中分配时间片才会执行
        * 8.执行start()时,底层会自动调用我们重写的业务方法run()
        * 9.线程的执行具有随机性,也就是说t1-t4具体怎么执行
        * 取决于CPU调度时间片的分配规则,我们是决定不了的*/
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

//1.自定义一个多线程类
class MyThread extends Thread{
    /*1.多线程编程实现的方案1:通过继承Thread类,并重写run()来完成的*/
    //2.重写run(),run()里是我们自己的业务
    @Override
    public void run() {
        /*2.super.run()表示这里调用的是父类的业务,但现在我们想用自己的业务,所以注释掉*/
        //super.run();

        //3.完成业务,打印10次当前正在执行的线程名称
        for (int i = 0; i < 10; i++) {
            /*3.getName()表示可以获取当前正在执行的线程名称
            * 由于本类继承了Thread类,所以可以直接使用Thread类提供的功能*/
            System.out.println(i+"="+getName());
        }
    }
}

2、实现Runnable接口

1)自定义自己的多线程类

2)实现run(),里面是我们自己的业务

3)创建自定义类的对象,作为唯一的业务对象

4)创建多个Thread类对象,作为多线程对象,并将业务对象target传入

5)使用多个线程对象调用start()对象

public class TestThread2 {
    public static void main(String[] args) {
        //4.创建自定义类的对象--目标业务类对象
        MyRunnable target = new MyRunnable();
        //5.启动线程,需要与Thread类建立关系
        Thread t1 = new Thread(target);//利用的是Thread的构造方法(Runnable target)
        Thread t2 = new Thread(target);
        Thread t3 = new Thread(target);
        Thread t4 = new Thread(target);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

//1.自定义多线程类
class MyRunnable implements Runnable{
    //2.添加父接口中未实现的抽象方法run(),里面是自己的业务
    @Override
    public void run() {
        //3.打印10次当前正在执行的线程名称
        for (int i = 0; i < 10; i++) {
            /*问题:自定义类与父接口Runnable中都没有获取线程名字的方法
            * currentThread():先通过这个静态方法,获取当前正在执行的线程对象
            * getName():然后获取这个线程对象的名字*/
            System.out.println(i+"="+Thread.currentThread().getName());
        }
    }
}

五、创建线程池的四种方式

1、newFixedThreadPool:创建一个固定长度线程池,可控制线程最大并发数,超出的线程会在队 列中等待。

2、newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

3、newScheduledThreadPool:创建一个固定长度线程池,支持定时及周期性任务执行。

4、newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值