进程与线程(Thread)

目录

一、相关概念

二、实现线程的两个方法 

方法一:

代码演示一:

代码演示二:

方法二:

代码演示:

三、多线程实现售票 

四、补充说明

1.sleep方法:

2.join方法:

3.join方法代码演示:

情况一:没有join方法

情况二:有join方法

五、思路图一张 


一、相关概念

  • 进程:正在运行的应用程序(官方概念:一个正在运行的程序拥有该程序运行的所有资源,包括资源的分配和任务调度。)
  • 线程:进程中的执行单元(作用:提升应用程序的执行效率)(官方概念:在进程中负责具体代码的执行,一个进程至少有一个线程。)
  • 并行:两个应用程序跑在两个不同的核上同时进行
  • 并发:交叉交替执行的任务

二、实现线程的两个方法 

方法一:

        创建一个类,继承Thread类,重写run方法,再调用start方法(单继承,有限制,有开辟线程的能力,资源共享方面不是很方便)

代码演示一:

MyThread类

public class MyThread extends Thread{
    @Override
    public void run(){
        run1();
    }
    
    public void run1(){
        for(int i = 0; i < 100; i++){
            System.out.println("MyThread---->" + i);
        }
    }
}

ThreadDemo类

package ThreadDemo;

public class ThreadDemo {
    public static void main(String [] args){
        MyThread myThread = new MyThread();
        myThread.start();
        for(int i = 0; i< 100; i++){
            System.out.println("main---->" + i);
        }
    }
}

运行结果:

 截取一小部分看个大概,知道意思就行^_^

代码演示二:

TicketsThread类

public class TicketsThread extends Thread{
    private int num;
    public  TicketsThread(){}
    public TicketsThread(int num){
        this.num = num;
    }

    public void setNum(int num){
        this.num = num;
    }
    public int getNum(){
        return this.num;
    }

    @Override
    public void run(){
        while(this.num > 0){
            sale();
        }
    }
    public void sale(){
        this.num = --num;
        System.out.println(Thread.currentThread().getName() + "Thread--->剩余票数:" + this.num);
        this.setNum(num);
    }
}

ThreadDemo类

public class ThreadDemo {
    public static void main(String [] args){
        TicketsThread ticketsThread = new TicketsThread(1000);
        ticketsThread.start();
        while(ticketsThread.getNum() > 0){
            ticketsThread.sale();
        }
    }
}

运行结果:

 卖票的过程为后面做铺垫。

方法二:

        实现Runnable接口,重新run方法。在传给Thread构造器,调用时调用Thread的start方法。(多实现,更灵活,推荐使用,没有开辟线程的能力,要将创建的对象交给指定线程来运行)。

代码演示:

RunnableTest类

public class RunnableTest implements Runnable{
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("分支线程" + i);
        }
    }
}

Test类

public class Test {
    public static void main(String [] args){
        RunnableTest1 r1 = new RunnableTest1();
        Thread t1 = new Thread(r1);
        t1.start();
        RunnableTest1 r2 = new RunnableTest1(){
            @Override
            public void run(){
                for(int i = 0; i< 100;i++){
                    System.out.println("main线程" + i);
                }
            }
        }; // 内部类
        Thread t2 = new Thread(r2);
        t2.start();
    }
}

运行结果:

三、多线程实现售票 

Tickets类

public class Tickets extends Thread{

    private int num;

    public Tickets(){}

    public Tickets(int num){
        this.num = num;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

Operate类

public class Operate {

    private Tickets tickets;

    public Operate(Tickets tickets){
        this.tickets = tickets;
    }

    public void sale(){
        synchronized (this){ //  synchronized   锁    同步    只能锁对象
            try{
                Thread.sleep(100);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        if(tickets.getNum() > 0){
            int num = tickets.getNum();
            System.out.println(Thread.currentThread().getName() + " 正在售卖 " + tickets.getNum() + " 张票,剩余 " + (tickets.getNum() - 1));
            num--;
            tickets.setNum(num);
        }
    }
}

Test类

public class Test {
    public static void main(String [] args){
        Tickets tickets = new Tickets(100);
        Operate operate = new Operate(tickets);

        new Thread(() -> {
            while(tickets.getNum() > 0) operate.sale();
        },"窗口一").start();

        new Thread(() -> {
            while(tickets.getNum() > 0) operate.sale();
        },"窗口二").start();

        new Thread(() -> {
            while(tickets.getNum() > 0) operate.sale();
        },"窗口三").start();
    }
}

运行结果:

 可以看到运行结果没有跟上面代码运行结果一样有重复值了

四、补充说明

1.sleep方法:

        是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但监控状态依然保持,到时间后会自动恢复为就绪状态。(sleep方法上面代码有演示,在这就不单独拿出来了)

2.join方法:

        作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。方法join具有使线程排队运行的作用,有些类似同步的运行效果。

3.join方法代码演示:

情况一:没有join方法

public class Test {
    public static void main(String [] args){
        System.out.println("main线程开始!");
        Thread t = new Thread(() -> {
            for(int i = 0; i < 100; i++){
                System.out.println("分支线程在执行--->" + i);
            }
        });
        t.start();
        System.out.println("main线程结束!");
    }
}

运行结果:

从上面可以清晰的看到虽然分支线程写在了中间,但是main线程的开始和结束是黏在一起的

情况二:有join方法

public class Test {
    public static void main(String [] args){
        System.out.println("main线程开始!");
        Thread t = new Thread(() -> {
            for(int i = 0; i < 100; i++){
                System.out.println("分支线程在执行--->" + i);
            }
        });
        t.start();
        for(int i = 0; i < 100; i++){
            if(i % 20 == 0){
                System.out.println("主线程让一次!");
            }
            System.out.println("main线程在执行--->" + i);
        }
        try {
            t.join(); // join方法也是一种阻塞的方式
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("main线程结束!");
    }
}

运行结果:

 

 从上面截图可以看到有join方法后main的开始和结束就完全分开了

五、思路图一张 

        感谢大家的阅读,如有错误还望指正,谢谢^_^ 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

还未被认可

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

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

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

打赏作者

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

抵扣说明:

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

余额充值