java(七) ——多线程

1.jvm与多线程

jvm里分为方法区、虚拟机栈、本地方法栈、堆、程序计数器
每个进程在方法区与堆里有一份
每个线程在虚拟机栈与程序计数器里有一份

2.java程序中自带的线程

一个java.exe程序中,至少存在三个线程:主线程、垃圾回收线程、异常处理线程

3.创建线程方式一:继承Thread类

/**
 * @author ym
 * @create 2022-01-24 17:38
 * @description 测试创建线程的方法,即继承thread类  得到100以内的所有偶数
 */
public class ThreadTest extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 1001; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
            }
        }
    }
}

/**
 * @author ym
 * @create 2022-01-24 17:40
 * @description
 */
public class ThreadTest1 {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
        for (int i = 0; i < 1001; i++) {
            if (i % 2 == 0) {
                System.out.println("main");
            }
        }
    }
}

注意:
1.不能用直接调用run方法的方式开启线程,这样的话只是相当于普通的函数调用,并没有打开新的线程
2.不能再调用一个start()过了的线程对象的start()方法

4.线程中常用方法

/**
 * @author ym
 * @create 2022-01-24 17:40
 * @description
 */
public class ThreadTest1 {
    /**
     * 线程中常用方法:
     * 1.start():启动当前线程,调用当前线程的run()方法
     * 2.run():重写Thread类中的此方法,将创建的线程要执行的内容声明在此处
     * 3.currentThread():静态方法,返回执行当前代码的线程
     * 4.getName():获取当前线程的名字
     * 5.setName():设置当前线程的名字
     * 6.yield():释放当前cpu的执行权
     * 7.join():在a线程中调用b线程的join()方法,则a线程会一直阻塞到b线程完全执行结束
     * 8.stop():已过时,当执行此方法时,强制结束当前线程
     * 9.sleep(long milltime):休眠,休眠期间当前线程是阻塞状态
     * 10.isAlive():判断当前线程是否存活
     *
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
//        5.setName():设置当前线程的名字
        Thread.currentThread().setName("主线程ym");
        //1.start():启动当前线程,调用当前线程的run()方法
        threadTest.start();
        for (int i = 0; i < 1001; i++) {
            if (i % 2 == 0) {
//                3.currentThread():静态方法,返回执行当前代码的线程
                //4.getName():获取当前线程的名字
                System.out.println(Thread.currentThread().getName() + "main\t" + i);

            }

            if (i == 800) {
//                7.join():在a线程中调用b线程的join()方法,则a线程会一直阻塞到b线程完全执行结束
                threadTest.join();
            }
            if (i == 900) {
//                8.stop():已过时,当执行此方法时,强制结束当前线程
                Thread.currentThread().stop();
            }
        }
    }
}

/**
 * @author ym
 * @create 2022-01-24 17:38
 * @description 测试创建线程的方法,即继承thread类  得到100以内的所有偶数
 */
public class ThreadTest extends Thread {

    //2.run():重写Thread类中的此方法,将创建的线程要执行的内容声明在此处
    @Override
    public void run() {
//        5.setName():设置当前线程的名字
        setName("测试线程ym");
        for (int i = 0; i < 1001; i++) {
            if (i % 2 == 0) {
                //3.currentThread():静态方法,返回执行当前代码的线程
                //4.getName():获取当前线程的名字
                System.out.println(currentThread().getName() + i);
            }
            if (i == 700) {
                try {
//                    9.sleep(long milltime):休眠,休眠期间当前线程是阻塞状态
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (i == 850) {
//                10.isAlive():判断当前线程是否存活
                System.out.println(isAlive());
            }
            if (i % 10 == 0) {
//                6.yield():释放当前cpu的执行权
                yield();
            }
        }
    }
}

5.创建线程的第二个方法:实现runnable接口

/**
 * @author ym
 * @create 2022-01-24 20:36
 * @description 第二种创建线程的方式,实现runnable接口
 */
public class ThreadTest2 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread = new Thread(myThread);
        thread.start();
        Thread thread1 = new Thread(myThread);
        thread1.start();
    }
}

class MyThread implements Runnable {

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i + "\t" + Thread.currentThread().getName());

            }
        }
    }
}

6.常见多线程初识问题:窗口卖票问题

需求:3个窗口共卖出100张票
实现方案1:用继承thread的方式,不过此时需注意,票数需要static

package com.exer;

/**
 * @author ym
 * @create 2022-01-24 20:12
 * @description   三个窗口卖票问题
 */
public class TicketDemo {
    public static int tickets = 100;

    public static void main(String[] args) {
        TicketSell ticketSell1 = new TicketSell();
        TicketSell ticketSell2 = new TicketSell();
        TicketSell ticketSell3 = new TicketSell();

        ticketSell1.start();
        ticketSell2.start();
        ticketSell3.start();
    }
}

class TicketSell extends Thread{
    @Override
    public void run() {
        while (true){
            if (TicketDemo.tickets>0){
                TicketDemo.tickets--;
                System.out.println(TicketDemo.tickets+"\t"+getName());
            }else {
                break;
            }
        }
    }
}

**实现方案2:用实现runnable接口的方式,此时便不需将票数static了,因为每个线程都共用一个实现了runnable的线程操作对象 **

package com.exer;

/**
 * @author ym
 * @create 2022-01-24 20:45
 * @description
 */
public class TicketDemo1 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();

        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        Thread thread3 = new Thread(myThread);

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

class MyThread implements Runnable {

    public int tickets = 100;

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                tickets--;
                System.out.println(Thread.currentThread().getName() + "\t" + tickets);
            } else {
                break;
            }

        }
    }
}

7.总结:在开发中,多线程创建尽量使用实现runnable()接口的方法,原因:

1.实现的方式没有类的单继承性的局限
2。实现的方式更适合来处理多个线程有共享数据的情况

上一篇:SpringBoot | 源码解析(一): SpringApplication.run


下一篇:core-js报错