多线程基础知识(上)

本文详细解析了Java线程的概念,介绍了创建线程的两种方法(继承Thread类和实现Runnable接口),并通过售票问题实例演示并发与并行的区别。还涵盖了线程终止的控制方式,适合初学者理解多线程编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

基本概念

程序:是为完成特定任务 用某种语言编写的一组指令的集合(也就是我们常说的代码)

进程:

线程:线程是由进程创建的实体 一个进程可以拥有一个或者多个线程  

单线程 同一时刻只允许执行一个线程 

多线程 同一时刻可以执行多个线程 

并发:同一个时刻 多个任务交替执行  造成一种“貌似同时”的错觉(hh)

并行:同一时刻 多个任务同时进行 多核cpu实现并行 

线程的使用

创建线程

第一种继承Thread类 重写run方法

总结

1.可以清晰得出两个线程是同时交替执行的

2.为什么p不直接调用run方法而是调用start方法呢 

第二种方法:实现Runnable接口

多线程售票问题

线程终止


前言

本文是博主学习韩顺平老师java课程后的笔记 韩老师yyds!

基本概念

程序:是为完成特定任务 用某种语言编写的一组指令的集合(也就是我们常说的代码)

进程:

是指运行中的程序  进程是程序的一次执行过程 或是正在运行的一个程序 是动态过程 有它自身的产生 生存 和 消亡的过程   比如我们打开qq 是一个进程  系统会为此分配资源和空间  再比如我们打开浏览器又是一个进程 系统会为它再次分配空间

线程:线程是由进程创建的实体 一个进程可以拥有一个或者多个线程  

单线程 同一时刻只允许执行一个线程 

我们打开qq音乐播放一首歌 发现自己只能听一首 切换了就是下一首了 这就相当于单线程的一种体现

多线程 同一时刻可以执行多个线程 

比如我们打开qq 群发消息就是多线程的一种体现 同时发送给了不同的人 

并发:同一个时刻 多个任务交替执行  造成一种“貌似同时”的错觉(hh)

 比如 典型的单核cpu行的多任务就是并发 

并发具体一点就是说 左手画圆右手画三角形 其实中间是有停顿的 但是速度一快就像是同时执行的

并行:同一时刻 多个任务同时进行 多核cpu实现并行 

具体一点就是说  jack在开车 jack's wife lucy在接电话  怎么样具体不具体 

线程的使用

创建线程

有两种方法

第一种继承Thread类 重写run方法

public class Pre01 {
    public static void main(String[] args) throws InterruptedException {
        P p = new P();
        //启动线程
        p.start();
        for (int i = 0; i < 80; i++) {
            //线程休眠 一秒钟  此处会有异常需要我们处理
            Thread.sleep(1000);
            System.out.println("主线程"+i);
        }
        System.out.println("主线程继续执行");
    }
}
class P extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i < 80; i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"线程被调用"+i);
    }
    }
}

执行结果如下(部分) 

Thread-0线程被调用9
主线程9
Thread-0线程被调用10
主线程10
主线程11
Thread-0线程被调用11
Thread-0线程被调用12
主线程12
Thread-0线程被调用13

总结

1.可以清晰得出两个线程是同时交替执行的

2.为什么p不直接调用run方法而是调用start方法呢 

请看源码 start源码在其中调用了start0方法

/* 1.start方法   
public synchronized void start() {
   start0();
}

start0方法中重写并调用了run方法  

2.start0方法
//真正实现多线程的效果是start0() 而不是run
//start方法调用start0方法后 该线程并不一定会马上执行  只是将线程变成了可运行状态 具体什么时候 取决于cpu
 private native void start0();
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

如果你单纯调用run方法的话 相当于调用了一个普通方法 并不会创建线程 这样会使得先执行run方法  再去执行主线程  本质上还是一个线程  

第二种方法:实现Runnable接口

第二种方法更好的满足适应了java单继承的特性  因为java只能单继承如果利用了第一种方法 那么就无法再继承其他的类了 所以我们一般来说更为推荐第二种方法 即通过实现接口来创建线程

public class Pre02 {
    public static void main(String[] args) throws InterruptedException{
        P1 p1 = new P1();
        //此处可以认为p1 转换成了Thread类 因为两者其实都实现了Runnable接口
        Thread thread = new Thread(p1);
        thread.start();
        for (int i = 0; i < 80; i++) {
            Thread.sleep(1000);
            System.out.println("主线程"+i);
        }
    }
}
class P1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 80; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
            System.out.println("子线程"+i);
        }
    }
}

总结:

1.两个方法没有本质上的区别 都实现了Runnable接口

2.关于P1那段描述可能不太准确 具体的底层机制我也还不了解  只是参考前面所学做出的推测

多线程售票问题

三个窗口共同卖一百张火车票 运用多线程实现

public class Pre03 {
    public static void main(String[] args) {
        D d = new D();
        D d1 = new D();
        D d2 = new D();
        d.start();
        d1.start();
        d2.start();
    }
}
class D extends Thread{
  private static int nums = 100;
//一共一百张票
    @Override
    public void run() {
        while(nums>=0){
            System.out.println(Thread.currentThread().getName()+"线程(窗口)售出了一张还有"+nums--+"张");
        }
    }
}

最后可能会出现超发的结果 这就牵扯到后面所说的锁的问题

线程终止

public class Thread05 {
    public static void main(String[] args) {
        T t = new T();
        Thread thread = new Thread(t);
        thread.start();
        //主线程控制t1线程的终止 必须可以修改loop
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
            t.setLoop(false);
       
    }
}
class T implements Runnable{
    private int count = 0;
    //设置一个控制变量
    private boolean loop = true;
    @Override
    public void run() {
    while(loop){

        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("ok"+count);
        count++;
    }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }

    public int getCount() {
        return count;
    }
}

1.当线程完成任务后 它会自动退出

2.还可以通过使用变量来控制run方法退出的方式停止线程 即通知方式

只要在努力 没有虚度时光 就没有什么好焦虑的  共勉!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值