JAVA基础学习入门(十)

java高级阶段部分开始

多线程

一、多线程的创建

首先来体会一下多线程,体会一下切片

/**多线程的创建,方式一:继承于Thread类
 * 1.创建一个继承于Thread类的子类
 * 2.重写Thread类的run()--->将此线程执行的操作声明在run()中
 * 3.创建Thread类的子类的对象
 * 4.通过此对象调用start()
 *
 * 例子:遍历100以内的所有的偶数
 * @author 123
 * @create 2022-03-23 8:37
 */

//1.创建一个继承于Thread类的子类
class MyThread extends Thread{
    //2.重写Thread类的run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i%2==0){
                System.out.println(i);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        //3.创建Thread类的子类的对象
        MyThread t1 = new MyThread();
        //4.通过此对象调用start()
        t1.start();

        for (int i = 0; i < 100; i++) {
            if (i%2!=0){
                System.out.println(i+"********main*********");
            }
        }
    }

}

通过输出结果你会发现这是交替进行的,根据每个人机器cpu的不同结果打印会不一样
在这里插入图片描述
在这里插入图片描述
如果不调用start方法而是直接调用run方法会怎么样呢?那样就只是开了一个线程,所有的都在main线程中执行了。如下图所示,就只是重写了一个方法再调用该方法,执行完该方法后又接着执行后面的代码。

/**多线程的创建,方式一:继承于Thread类
 * 1.创建一个继承于Thread类的子类
 * 2.重写Thread类的run()--->将此线程执行的操作声明在run()中
 * 3.创建Thread类的子类的对象
 * 4.通过此对象调用start()
 *
 * 例子:遍历100以内的所有的偶数
 * @author 123
 * @create 2022-03-23 8:37
 */

//1.创建一个继承于Thread类的子类
class MyThread extends Thread{
    //2.重写Thread类的run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i%2==0){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        //3.创建Thread类的子类的对象
        MyThread t1 = new MyThread();
        //4.通过此对象调用start() ①启动当前线程 ②调用当前线程的run()
       // t1.start();//start方法自动去调用上面那个被重写的run方法了,所以start方法的作用到底是什么呢?
        t1.run();


        //如下操作仍然是在main线程中执行的
        for (int i = 0; i < 100; i++) {
            if (i%2!=0){
                System.out.println(Thread.currentThread().getName()+":"+i+"********main*********");
            }
        }
    }

}

在这里插入图片描述
所以必须通过调用start方法去启动线程,这样结果明显能看出来是有两个线程存在
在这里插入图片描述
那么我用t1去两次调用start来开启两个线程可以吗?答案是不可以的

public class ThreadTest {
    public static void main(String[] args) {
        //3.创建Thread类的子类的对象
        MyThread t1 = new MyThread();
        //4.通过此对象调用start() ①启动当前线程 ②调用当前线程的run()
        t1.start();//start方法自动去调用上面那个被重写的run方法了,所以start方法的作用到底是什么呢?
        //问题一:我们不能通过直接调用run()的方式启动线程
        //t1.run();

        //问题二:再启动一个线程,遍历100以内的偶数。不可以还让start()的线程去执行。会报IllegalThreadStateException
      //  t1.start();
        //我们需要重新创建一个线程的对象
        MyThread t2 = new MyThread();
        t2.start();


        //如下操作仍然是在main线程中执行的
        for (int i = 0; i < 100; i++) {
            if (i%2!=0){
                System.out.println(Thread.currentThread().getName()+":"+i+"********main*********");
            }
        }
    }

}

在这里插入图片描述
在这里插入图片描述
总结:要想造多个线程只能通过造多个线程对象,要想启动这些线程,只能通过这些线程对象去调用start( )方法。

上述创建多线程的方法分为四个步骤,咱们可以通过创建Thread类的匿名子类方式来将这几步简化融合一下,实现不同线程执行不同的事情,如下图所示:

public class ThreadDemo {
    public static void main(String[] args) {
        //创建Thread类的匿名子类的方式
        new Thread(){
            @Override
            public void run() { //偶数
                for (int i = 0; i < 100; i++) {
                    if (i%2==0){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() { //奇数
                for (int i = 0; i < 100; i++) {
                    if (i%2!=0){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
        }.start();
    }
}

二、Thread类中的常用方法

在这里插入图片描述
在这里插入图片描述
我们可以通过setName函数给线程命名,也可以通过构造器的方式给线程命名。

/**
 * 测试Thread中的常用方法
 * 1.start():启动当前进程:调用当前线程的run()
 * 2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
 * 3.currentThread():静态方法,返回执行当前代码的线程
 * 4.getName():获取当前线程的名字
 * 5.setName():设置当前线程的名字
 * @author 123
 * @create 2022-03-23 10:12
 */
class HelloThread 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 HelloThread(String name){
        super(name);
    }
}
public class ThreadMethod {
    public static void main(String[] args) {

        HelloThread h1 = new HelloThread("Thread:1");
        //h1.setName("线程一");
        h1.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }

        }
    }
}

在这里插入图片描述

class HelloThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i%2==0){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
            if (i%20==0){
                this.yield();//表示想该线程想释放执行权,释放后可能(是可能不是一定)会被其他线程掌握执行权然后操作其他线程
            }
        }
    }
    public HelloThread(String name){
        super(name);
    }
}
public class ThreadMethod {
    public static void main(String[] args) {

        HelloThread h1 = new HelloThread("Thread:1");
        //h1.setName("线程一");
        h1.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }

        }
    }
}

在这里插入图片描述
如上图所示,20满足那个if条件,所以执行yield函数,释放执行权了,然后接着就被主线程抢去了
又补充了关于sleep和isAlive的用法,如下所示:

/**
 * 测试Thread中的常用方法
 * 1.start():启动当前进程:调用当前线程的run()
 * 2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
 * 3.currentThread():静态方法,返回执行当前代码的线程
 * 4.getName():获取当前线程的名字
 * 5.setName():设置当前线程的名字
 * 6.yield():释放当前cpu的执行权
 * 7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态、
 * 8.stop():已经过时,当执行此方法时,强制结束当前进程
 * 9.sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前线程是阻塞状态
 * 10.isAlive():判断当前线程是否存活
 * @author 123
 * @create 2022-03-23 10:12
 */
class HelloThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i%2==0){
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
            if (i%20==0){
                this.yield();//表示想该线程想释放执行权,释放后可能(是可能不是一定)会被其他线程掌握执行权然后操作其他线程
            }
        }
    }
    public HelloThread(String name){
        super(name);
    }
}
public class ThreadMethod {
    public static void main(String[] args) {

        HelloThread h1 = new HelloThread("Thread:1");
        //h1.setName("线程一");
        h1.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
            if(i==20){
                try {
                    h1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(h1.isAlive());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值