• Java多线程(一)



    提示:以下是本篇文章正文内容,下面案例可供参考

    一、程序、进程、线程基本概念

    1.程序(program)

    是为完成特定任务、用某种语言编写的一组指令的集合。即指段静态的代码,静态对象

    2.进程(process)

    是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。一一生命周期

    程序是静态的,进程是动态的
    进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域

    3.线程(thread)

    进程可进一步细化为线程,是一个程序内部的一条执行路径
    1.若一个进程同一时间并行执行多个线程,就是支持多线程的
    2.线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
    3.一个进程中的多个线程共享相同的内存单元/内存地址空间,它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。[

    二、单核CPU和多核CPU的理解

    1.单核CPU,其卖是一种假的多线程,因为在一个时间单元内,也只能执行 一个线程的任务。
    2.如果是多核的话,才能更好的发挥多线程的效率
    3.一个Java应用程序java.exe,其实至少有三个线程: main()主线程,gc()垃圾回收线程,异常处理线程。当然如果发生异常,会影响主线程。

    三、并行和并发

    1.并行

    多个CPU同时执行多个任务

    2.并发

    一个CPU(采用时间片)同时执行多个任务。

    四、创建多线程的方式一(继承Thread类)

    1.创建两个分线程,其中一个线程遍历100以内的偶数,另外一个线程遍历100以内的奇数

    package com.tyust.java1;
    
    /**
     * @author YML TYUST-XDU 2019-2026
     * @create 2023-09-22 8:08
     * 创建两个分线程,其中一个线程遍历100以内的偶数,另外一个线程遍历100以内的奇数
     */
    public class ThreadDemo {
        public static void main(String[] args) {
    //        MyThread1 m1 = new MyThread1();
    //        MyThread2 m2 = new MyThread2();
    
    //        m1.start();
    //        m2.start();
    
    
            //创建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();
    
    
        }
    }
    
    class MyThread1 extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if(i % 2 == 0)
                    System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    class MyThread2 extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if(i % 2 != 0)
                    System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    2.售票案例

    package com.tyust.java2;
    
    /**
     * @author YML TYUST-XDU 2019-2026
     * @create 2023-09-22 8:57
     */
    class Window extends Thread{
    
        private static int ticket = 100;
    
        @Override
        public void run() {
            while(true){
                if(ticket > 0){
                    System.out.println(Thread.currentThread().getName() + ": 卖票,票号为:" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
    
    
    
    public class WindowTest {
        public static void main(String[] args) {
            Window w1 = new Window();
            Window w2 = new Window();
            Window w3 = new Window();
    
            w1.setName("窗口一");
            w2.setName("窗口二");
            w3.setName("窗口三");
    
            w1.start();
            w2.start();
            w3.start();
            
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    五、测试Thread中的常用方法

    1 .测试Thread中的常用方法

    • 1.start():启动当前前程;调用当前线程的run()
    • 2.run():通常需要重写Thread类中的run(),将创建的线程要执行的操作声明再此方法中
    • 3.currentThread():静态方法,返回执行当前代码的线程
    • 4.getName();获取当前线程的名字
    • 5.setName():设置当前线程的名字
    • 6.yield(): 释放当前cpu的执行权
    • 7.join():在线程A中调用线程B的join(),此时线程A九进入阻塞状态
    • 直到线程B完全执行完以后,线程A才结束阻塞状态
    • 8.stop():已过时,当执行此方法时,强制结束当前线程。
    • 9.sleep(long millitime):让当前线程”睡眠“指定的millitime毫秒,
    • 10.isAlive();判断当前线程是否存活

    2.代码

    class HelloThread extends Thread{
        public void run() {
            for (int i = 0; i < 100; i++) {
    
                if(i % 2 != 0){
    //                try {
    //                    sleep(10);
    //                } catch (InterruptedException e) {
                        throw new RuntimeException(e);
    //                    e.printStackTrace();
    //                }
                    System.out.println(Thread.currentThread().getName()+":"+i + ":"+Thread.currentThread().getPriority());
                }
    //            if(i%20 == 0)
    //                this.yield();
    
    
            }
        }
    
        public HelloThread(String name){
            super(name);
        }
    
    
    }
    
    
    public class ThreadMethodTest {
        public static void main(String[] args) {
            HelloThread h1 = new HelloThread("thread:1");
    //        h1.setName("线程一");
    
            //设置分线程的优先级
            h1.setPriority(Thread.MAX_PRIORITY);
            h1.start();
    
            //
            Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
            Thread.currentThread().setName("主线程");
    
            int i = 0;
    
            for (i = 0; i < 100; i++) {
                    if(i % 2 == 0)
                        System.out.println(Thread.currentThread().getName()+":"+i+ ":"+Thread.currentThread().getPriority());
    
    //            if(i == 20){
    //                try {
    //                    h1.join();
    //                } catch (InterruptedException e) {
    //                    throw new RuntimeException(e);
    //                }
    //            }
            }
    
            System.out.println(h1.isAlive());
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    六、创建多线程的方式二(实现Runnable接口)

    1.步骤

    *1.创建一个实现了Runnable接口的类
    *2.实现类去实现Runnable中的抽象方法: run()
    *3,创建实现类的对象
    *4,将此对象作为参最传遗到Thread类的构造器中,创建Thread类的对象
    *5.通过Thread类的对象调用start()

    2.代码实现

    package com.tyust.java2;
    
    /**
     * @author YML TYUST-XDU 2019-2026
     * @create 2023-09-22 9:09
     */
    //1.创建一个实现了Runnable接口的类
    class mThread implements Runnable{
        @Override
        //2.实现类去实现Runnable中的抽象方法: run()
        public void run() {
            for (int i = 0; i < 100; i++) {
                if(i%2 == 0)
                {
                    System.out.println(Thread.currentThread().getName() + i);
                }
            }
        }
    }
    
    
    
    public class ThreadTest1 {
        public static void main(String[] args) {
        	//3.创建实现类的对象
            mThread mt = new mThread();
            //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
            Thread t1 = new Thread(mt);
            //5.通过Thread类的对象用start():①启动线程 ②调用当前线程的run()-->调用了Runnable类型的target的run()
            t1.start();
    
            //再创建一个线程
            Thread t2 = new Thread(mt);
            t2.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    3.比较创建线程的两种方式

    开发中:优先选择:实现Runnable接口的方式

    原因:1.实现的方式没有类的单继承性的局限性
    2.实现的方式更适合来处理多个线程有共享数据的情况
    联系: public class Thread implements Runnable
    相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中,
    目前两种方式,要想启动线程,都是调用的Thread类中的start()

    4.售票案例

    package com.tyust.java2;
    
    /**
     * @author YML TYUST-XDU 2019-2026
     * @create 2023-09-22 9:19
     */
    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 WindowTest1 {
        public static void main(String[] args) {
            Window1 w = new Window1();
            Thread t1 = new Thread(w);
            Thread t2 = new Thread(w);
            Thread t3 = new Thread(w);
            t1.setName("窗口一");
            t2.setName("窗口二");
            t3.setName("窗口三");
    
            t1.start();
            t2.start();
            t3.start();
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    七、线程的优先级

    1.常量

    MAX_PRIORITY:10
    MIN_PRIORITY: 1
    NORM_PRIORITY: 5-->默认优先级
    
    • 1
    • 2
    • 3

    2.获取、设置优先级

    getPriority():获取线程的优先级
    setPriority(int p): 设置线程的优先级
    
    • 1
    • 2

    3.说明

    高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下被执行。并不意味着只当高优先级的线程执行完以后,低优先级的线程才执行。


  • 相关阅读:
    R语言的计量经济学技术
    Java获取/resources目录下的资源文件方法
    播放量暴涨2000w+,单日狂揽24w粉,内卷的搞笑赛道还有机会
    个人课设---玩家血条(包括攻击掉血,复活重生功能)
    腾讯云发布智慧员工管理方案,支持组织360度协作
    第四十二天 哈希
    计算数列的微分(整数阶微分)
    浅谈常态化压测 | 京东物流技术团队
    Unity3D PRO 3D游戏制作系列教程第三课:认识菜单一
    Hadoop 集群配置 SSH
  • 原文地址:https://blog.csdn.net/lalalalalab/article/details/133160448