多线程基础

第一章 进程和线程

1.1进程的介绍

是一个程序的运行状态和资源占用(内存,CPU)的描述
进程是程序的一个动态过程,它指的是从代码加载到执行完毕的一个完成过程
进程的特点:
a.独立性:不同的进程之间是独立的,相互之间资源不共享(举例:两个正在上课的教室有各自的财产,相互之 间不共享)

b.动态性:进程在系统中不是静止不动的,而是在系统中一直活动的
c.并发性:多个进程可以在单个处理器上同时进行,且互不影响

1.2线程的介绍

是进程的组成部分,一个进程可以有多个线程,每个线程去处理一个特定的子任务
线程的执行是抢占式的,多个线程在同一个进程中可以并发执行,其实就是CPU快速的在不同的线程之间切换,也就是 说,当前运行的线程在任何时候都有可能被挂起,以便另外一个线程可以运行

1.3进程和线程的关系以及区别

a.一个程序运行后至少有一个进程
b.一个进程可以包含多个线程,但是至少需要有一个线程,否则这个进程是没有意义的
c.进程间不能共享资源,但线程之间可以
d.系统创建进程需要为该进程重新分配系统资源,而创建线程则容易的多,因此使用线程实现多任务并发比多进程的效率高
e.系统创建进程需要为该进程重新分配系统资源,而创建线程则容易的多,因此使用线程实现多任务并发比多进程的效率高

第二章 多线程的实现

2.1继承Thread类

继承自Thread类,Thread类是所有线程类的父类,实现了对线程的抽取和封装
继承Thread类创建并启动多线程的步骤:
a.定义一个类,继承自Thread类,并重写该类的run方法,该run方法的方法体就代表了线程需要完成的任务, 因此,run方法的方法体被称为线程执行体
b.创建Thread子类的对象,即创建了子线程c.用线程对象的start方法来启动该线程

public class ThreadUsageDemo01 {

    public static void main(String[] args) {

        //创建线程对象
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        //给线程取名字
        myThread1.setName("线程1");
        myThread2.setName("线程2");

        //启动线程
        myThread1.start();
        myThread2.start();

        //获取当前线程
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());

        //通过构造方法创建线程
        MyThread3 myThread3 = new MyThread3("新线程");
        //启动线程
        myThread3.start();


    }

}

class MyThread extends Thread {

    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName());
        }

    }

}

//线程类
class MyThread3 extends Thread {
    public MyThread3() {

    }

    public MyThread3(String name) {
        super(name);//调用的父类中的Thread(String name)
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

结果:
在这里插入图片描述
**结论:**每次运行的结果都不一样,因为线程是谁抢占了资源谁就先调用!

案例:模拟售票员售票

public class ThreadTestDemo01 {

    public static void main(String[] args) {


        SellTickets sellTickets1 = new SellTickets();
        SellTickets sellTickets2 = new SellTickets();
        SellTickets sellTickets3 = new SellTickets();
        SellTickets sellTickets4 = new SellTickets();

        sellTickets1.start();
        sellTickets2.start();
        sellTickets3.start();
        sellTickets4.start();
    }

}

/**
 * 模拟车票售票
 */
//线程类
class SellTickets extends Thread{

    public static int count = 100;

    @Override
    public void run() {


        while (count>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            count--;
            System.out.println("线程是"+Thread.currentThread().getName()+"剩余车票是"+count);
        }
    }
}

结果:
在这里插入图片描述

因为线程在竞争的过程中,CPU的切换是非常快的,可能线程1正好执行完count–的时候,线程已经切换到了线程2,此时count–又再执行了一次,导致跳过了一张票没有卖出,或者,当线程1恰好正好将要执行count–但还没执行的时候,线程已经切换到了线程2,此时因为线程1并没有进行count–操作,线程2卖出了重复的同一张票以后,才执行了count–,导致出现了同一张票重复销售的情况。
此时,我们需要引入线程锁的概念,以解决线程的同步问题。

2.2实现Runnable接口

实现Runnable接口创建并启动多线程的步骤:
a.定义一个Runnable接口的实现类,并重写该接口中的run方法,该run方法的方法体同样是该线程的线程执行

b.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真 正的线程对象
c.调用线程对象的start方法来启动该线程

public class ThreadUsageDemo02 {

    public static void main(String[] args) {

        //创建对象
        check check = new check();
        Thread thread = new Thread(check);
        thread.start();

        Thread thread1 = new Thread(check);
        thread1.start();

    }
}


class check implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "ik");
        }
    }
}

结果:
在这里插入图片描述

案例:模拟售票员售票

public class ThreadTextDemo02 {

    static int count = 100;//票数

    static Runnable runnable = new Runnable() {
        @Override
        public void run() {

            while (count > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println(Thread.currentThread().getName() + "售票一张,剩余" + count);
            }
        }

    };

    public static void main(String[] args) {

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        Thread thread3 = new Thread(runnable);
        Thread thread4 = new Thread(runnable);

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();


    }

}

结果:
在这里插入图片描述

2.3实现Callable接口

public class FutureTaskTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建线程对象
        CallableTest callableTest = new CallableTest();

        //通过线程对象创建
        FutureTask<Integer> integerFutureTask = new FutureTask<>(callableTest);

        //启动
        Thread thread = new Thread(integerFutureTask, "线程1");
        thread.start();

        //获取线程运行的值
        Integer integer = integerFutureTask.get();
        System.out.println(integer);

    }
    
}

//线程类
class CallableTest implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
            sum += i;
        }

        return sum;
        
    }
}

结果:
在这里插入图片描述

2.4实现方式的比较

实现Runnable接口的方式
a.线程类只是实现了Runnable接口,还可以继承其他类【一个类在实现接口的同时还可以继承另外一个类】
b.可以多个线程共享同一个target对象,所以非常适合多个线程来处理同一份资源的情况
c.弊端:编程稍微复杂,不直观,如果要访问当前线程,必须使用Thread.currentThread()
继承Thread类的方式:
a.编写简单,如果要访问当前线,程除了可以通过Thread.currentThread() 方式之外,还可以使用super关键字
b.弊端:因为线程类已经继承了Thread类,则不能再继承其他类【单继承】

实际上大多数的多线程应用都可以采用实现Runnable接口的方式来实现【推荐使用匿名内部类】

2.5调用start()与run()方法的区别

当调用start()方法时将创建新的线程,并且执行run()方法里的代码,但是如果直接调用start()方法,不会创建新的线程也不会执行调用线程的代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值