Java中的进程与多线程(Thread、Runnable、Callable)

进程与线程之间的关系

  • 二者均可并发执行.
  • 线程是指进程内的一个执行单元,也是进程内的可调度实体。一个程序至少有一个进程,一个进程至少有一个线程,一个线程只属于一个进程.
  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
  • 处理机分给线程,即真正在处理机上运行的是线程。
  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。而线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
  • 通俗的说,进程是指运行中的程序,比如QQ,启动就可以在任务管理器中看到QQ的进程。线程由进程创建的,是进程的一个实体,一个进程至少有一个线程,可以有多个线程。线程就差不多是进程里面产生的子任务,每子任务有着各自的事情需要做

进程与线程的区别

  • 根本区别 :进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
  • 在操作系统中能同时运行多个进程,进程中会执行多个线程
  • 线程是操作系统能够进行运算调度的最小单位

并发与并行

  • 并发:不同代码块交替执行
  • 并行:不同代码块同时执行

线程状态

创建、就绪、运行、阻塞、死亡
在这里插入图片描述
在这里插入图片描述

创建线程的三种方式

方式一:继承Thread

继承Thread基类,重写run方法,调用start()方法启动线程
不建议使用:避免单继承局限性

/**
 * 创建线程方法一:Thread
 * 继承Thread基类,重写run方法
 */
public class testthread01 extends Thread{

    @Override
    public void run() {
        for (int i=0;i<200;i++){
            System.out.println("我在学习多线程---"+i);
        }
    }

    public static void main(String[] args) {
//        创建一个线程对象
        testthread01 testthread01 = new testthread01();
//        调用start()方法开启线程
        testthread01.start();

    }

}

方式二:实现Runnable接口

实现Runnable接口,重写run方法,创建线程对象(Thread作为代理对象),调用start()方法启动线程
推荐使用:避免Java单继承的局限性,灵活方便,方便同一个对象被多个线程使用
Runnable对象的优点 同一个对象被多个线程使用,同时也是缺点 触发多个线程操作同一个资源(同一线程对象)的情况下,线程不安全,数据撩乱

/**
 * 创建线程方法二:Runnable
 * 实现Runnable接口,重写run方法
 * 发现问题:多个线程操作同一个资源(同一线程对象)的情况下,线程不安全,数据撩乱
 */
public class testrunnable03 implements Runnable{
    public int num=10;

    @Override
    public void run() {
        while (num>0){
//            模拟延时
            try {
                Thread.sleep(200);
            }catch (InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("我"+Thread.currentThread().getName()+":"+num--);
        }

    }

    public static void main(String[] args) {
        testrunnable03 t1 = new testrunnable03();
        new Thread(t1,"刘备").start(); //Thread 代理对象
        new Thread(t1,"关羽").start();
        new Thread(t1,"张飞").start();

    }
}

方式三:实现Callable接口

实现Callable接口,重写call方法,有返回值
较少使用,可作为扩展学习

import java.util.concurrent.*;
/**
 * 创建线程方法三:Callable
 * 实现Callable接口,重写call方法,有返回值
 */
public class testcallable04 implements Callable<Boolean> {

    String name;
    static int num=0;


    public testcallable04(String name){
        this.name = name;
    }

    @Override
    public Boolean call() {
        while (num<100){
            num++;
            System.out.println(name+"-->"+num);
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        testcallable04 t1 = new testcallable04("刘备");
        testcallable04 t2 = new testcallable04("关羽");
        testcallable04 t3 = new testcallable04("张飞");

//        创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);

//        提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

//        获取结果
        Boolean b1 = r1.get();
        Boolean b2 = r2.get();
        Boolean b3 = r3.get();

//        关闭服务
        ser.shutdownNow();

    }

}

线程例子:龟兔赛跑

/**
 * 模拟龟兔赛跑
 */
public class Race implements Runnable{

//    胜利者
    private  static String winner;

    @Override
    public void run() {

        for (int i = 0; i <= 100; i++) {

            if (Thread.currentThread().getName().equals("兔子")){
                try{
                    Thread.sleep(10);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

            if (gameover(i)){
                break;
            }

            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }

    }

    public boolean gameover(int steps){

        if (winner != null){
            return true;
        }else {
            if (steps >= 100){
                winner = Thread.currentThread().getName();
                System.out.println("胜利者:"+winner);
                return true;
            }
        }

        return false;

    }


    public static void main(String[] args) {

        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

纯属个人经验,喜欢的可以点赞关注,后续见!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙卷风爱卷

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值