Java多线程1(线程创建)

本文深入介绍了Java中的线程概念,包括进程、线程、多线程的串行与并行执行。通过实例展示了通过继承Thread类和实现Runnable接口两种方式创建多线程,并探讨了线程的生命周期状态,如新建、就绪、运行、阻塞和死亡。此外,还讨论了线程控制方法,如sleep、yield和join。最后,提到了线程的中止策略。
摘要由CSDN通过智能技术生成

一 线程与进程

什么是进程?
电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管家等等。在这里插入图片描述

什么是线程?
进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。

那什么是多线程?提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程。

1.串行,其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子:当我们下载多个文件时,在串行中它是按照一定的顺序去进行下载的,也就是说,必须等下载完A之后才能开始下载B,它们在时间上是不可能发生重叠的。

2.并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻发生的,并行在时间上是重叠的。

了解了这两个概念之后,我们再来说说什么是多线程。举个例子,我们打开腾讯管家,腾讯管家本身就是一个程序,也就是说它就是一个进程,它里面有很多的功能,我们可以看下图,能查杀病毒、清理垃圾、电脑加速等众多功能。
按照单线程来说,无论你想要清理垃圾、还是要病毒查杀,那么你必须先做完其中的一件事,才能做下一件事,这里面是有一个执行顺序的。
如果是多线程的话,我们其实在清理垃圾的时候,还可以进行查杀病毒、电脑加速等等其他的操作,这个是严格意义上的同一时刻发生的,没有执行上的先后顺序。以上就是,一个进程运行时产生了多个线程。

二 实现多线程的两种方式

1.继承Thread类的方式

1.创建一个继承于Thread类的子类
2.重写Thread类的run()
3.创建Thread类的子类的对象
4.通过此对象调用start() ①启动当前线程②调用当前线程run()

简单例子1
class MyThread extends Thread{
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName()+":"+ i);
            }
        }
    }
}
public class ThreadDemo{
    public static void main(String[] args){
        MyThread t1 = new MyThread();
        t1.start();

        MyThread t2 = new MyThread();
        t2.start();
    }
}

2.Runnable接口的方式

1.创建一个实现了Runnable接口的类
2.重写该类中的Runnable接口中的抽象方法run()
3.创建此类的实例对象
4.将此对象作为参数传递到Thread类的构造器,创建Thread类的对象
5.通过Thread类的对象调用start():①启动线程②调用当前线程的
run–>调用Runnable类型的target的run()

源码

/*
传入Runnable接口实现
Thread(Runnable target)
传入Runnable接口实现,传入线程名
Thread(Runnable target, String name)


Thread类重写了Runnable接口的run()方法。
 该run()方法首先判断当前是否有Runnable的实现target存在。
 如果存在就执行target.run()

@Override
public void run() {
        if (target != null) {
        target.run();
        }
}

*/
简单例子1
class MThread implements Runnable{
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            if(i % 2 ==0){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args){
        MThread mThread = new MThread();

        Thread t1 = new Thread(mThread);
        t1.setName("线程一");
        t1.start();

        Thread t2 = new Thread(mThread);
        t2.setName("线程二");
        t2.start();
    }
}
例题:使用多线程创建三个窗口买票,总共100张票

1.使用Thread类继承方式

class Window extends Thread{
    private static int ticket = 100;
    @Override
    public void run(){
        while(true){
            if(ticket > 0){
                System.out.println(getName()+":买票,票号:"+ ticket);
                ticket--;
            }else{
                break;
            }
        }
    }
}
public class ThreadDemo3 {
    public static void main(String[] args){
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

2.使用Runnable接口方式

class Window1 implements Runnable{
    private int ticket = 100;
    @Override
    public void run(){
        while(true){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName()+"买票,票号为:"+ ticket);
                ticket --;
            }else{
                break;
            }
        }
    }

}
public class ThreadDemo4 {
    public static void main(String[] args){
        Window1 w = new Window1();

        Thread th1 = new Thread(w);
        Thread th2 = new Thread(w);
        Thread th3 = new Thread(w);

        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");

        th1.start();
        th2.start();
        th3.start();

    }
}

三 获取线程的名字,优先级等属性

1.获取当前对象
Thread t = Thread.currentThread(),t就是当前的线程
2.获取或修改线程对象的名字
String name = 线程对象.getName()/.setName(“xxx”)
3.获取与设设置线程的优先级

class MyThread2 extends Thread{
    public void run(){
        for (int i = 0; i < 100; i++){
            //Alt+Enter自动改错
            //让当前线程进入休眠,进入阻塞状态

            /*
            try {

                Thread.sleep(1000*2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            */

            //currentThread就是当前线程对象
            //当t1执行run方法,当前线程就是t1
            //当t2执行run方法,当前线程就是t2
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread.getName() + "默认优先级"+Thread.currentThread().getPriority()
                    +"-->" + i);
        }
    }
}
public class Demo5 {
    public static void main(String args[]){
        MyThread2 t1 = new MyThread2();
        t1.setName("t1");
        t1.setPriority(1);
        System.out.println(t1.getName());

        //如果这行代码出现在主线程中,获得的就是主线程的名字main
        System.out.println(Thread.currentThread().getName());

        MyThread2 t2 = new MyThread2();
        t2.setName("t2");
        System.out.println(t2.getName());

        t1.start();
        //t2.start();

        for(int i = 0; i < 100; i++){
            System.out.println(Thread.currentThread().getName()+"该线程默认优先级"+
            Thread.currentThread().getPriority()+' '+i);
        }

    }

}

四 线程的状态与状态管理

线程的五种状态:
1.新建状态
2.就绪状态
3.运行状态
4.阻塞状态
5.死亡状态
在这里插入图片描述

在这里插入图片描述

1、线程睡眠—sleep:

线程睡眠的原因:线程执行的太快,或需要强制执行到下一个线程。

线程睡眠的方法(两个):
sleep(long millis)在指定的毫秒数内让正在执行的线程休眠。
sleep(long millis,int nanos)在指定的毫秒数加指定的纳秒数内让正在执行的线程休眠。

2、线程让步—yield:

该方法和sleep方法类似,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但是不会进入阻塞状态,而是直接进入就绪状态。相当于只是将当前线程暂停一下,然后重新进入就绪的线程池中,让线程调度器重新调度一次。也会出现某个线程调用yield方法后暂停,但之后调度器又将其调度出来重新进入到运行状态。

sleep()方法与yield()方法的区别

1)sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给优先级低的线程以运行的机会,而yield()方法只会给相同优先级或者更高优先级的线程以运行机会。
2)
sleep()可以理解为“抱着资源睡觉”,由原来的运行状态进入阻塞状态,当时间到达,再由阻塞状态回到就绪状态,等待CPU的调度。
yield()直接由运行状态跳回就绪状态,表示退让线程,让出CPU,让CPU调度器重新调度。礼让可能成功,也可能不成功,也就是说,回到调度器和其他线程进行公平竞争。

3)sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常。
4)sleep()方法比yield()方法(跟操作系统)具有更好的可移植性。

3、线程合并—join:

JAVA多线程中join()方法的详细分析
当B线程执行到了A线程的.join()方法时,B线程就会等待,等A线程都执行完毕,B线程才会执行。
join可以用来临时加入线程执行。

4、线程的中止

【多线程】——停止线程的三种方式

五 实现多线程的更多方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值