IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java-Ch 8:多线程 1 (基础概念,创建方式) -> 正文阅读

[Java知识库]Java-Ch 8:多线程 1 (基础概念,创建方式)

目录

1. 程序、进程、线程

1.1 概念

?1.2 单核CPU和多核CPU

1.3 多线程优点(单核为何需要多线程?)

?

1.4 何时需要多线程?

1.5 辨析1(能拿一条线画出来就不是多线程)

??

1.6?代码示例

1.6.1 线程创建方式1(alt+enter快速造对象)

1.6.2 创建两个线程,匿名子类

1.6.3 线程的创建方式2(Runnable接口)

1.6.4 两者对比

1.7 Thread类的方法

1.8 线程的优先级

1.9 线程的分类

2 多窗口卖票

2.1 使用继承Thread类的方式

2.3 使用实现Runnable接口的方式(p)

2.4 接口方法更好


1. 程序、进程、线程

1.1 概念

程序:一段静态代码。

进程:运行中的程序,有生命周期。

线程 (thread) (室友+厨房):一个进程里面可以有多个线程,并行执行。main就对应一个线程。

?1.2 单核CPU和多核CPU

单核:主频高,轮流执行各个线程,伪多线程。

多核:根据不同业务启动不同的核。

并行与并发:

1.3 多线程优点(单核为何需要多线程?)

1.4 何时需要多线程?

1.5 辨析1(能拿一条线画出来就不是多线程)

?

1.6?代码示例

1.6.1 线程创建方式1(alt+enter快速造对象)

问题一:我们启动一个线程,必须调用start(),不能调用run()的方式启动线程。
问题二:如果再启动一个线程,必须重新创建一个Thread子类的对象,调用此对象的start().

package com.lee.java;

/**
 * 多线程的创建,方式一:继承于Thread类
 * 1. 创建一个继承于Thread类的子类
 * 2. 重写Thread类的run():将线程要做的事情放到方法体当中
 * 3. 创建Thread类的子类对象:在主线程
 * 4. 通过此对象调用start()
 *
 * 例子:遍历100以内的所有偶数
 *
 * @author Lee
 * @create 2021-08-11 23:33
 */

//1. 创建一个继承于Thread类的子类
class MyThread extends Thread {
    @Override
    public void run() {
        //2. 重写Thread类的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(); //alt+enter 自动创建对象

        //4. 通过此对象调用start():1.启动当前线程 2.调用当前线程的run()
        //主线程调方法:
        t1.start();
        //Q1:我们不能通过直接调用run()的方式启动线程
//        t1.run();//都是主线程

        //问题二:在启动一个线程,遍历100以内的偶数、
//        t1.start();//对于一个线程只能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******");
            }
        }
    }
}

1.6.2 创建两个线程,匿名子类

package com.lee.exer;

/**
 * 练习:创建两个线程。一个线程遍历100以内的偶数,另一个遍历100以内的奇数。
 * @author Lee
 * @create 2021-08-12 22:08
 */
public class ThreadDemo extends Thread{
    public static void main(String[] args) {
//        OddThread t1 = new OddThread();
//        t1.start();
//
//        EvenThread t2 = new EvenThread();
//        t2.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 == 1) {
                        System.out.println(Thread.currentThread().getName() + ":" + i);
                    }
                }
            }
        }.start();
    }
}

class OddThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 1) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

class EvenThread 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.6.3 线程的创建方式2(Runnable接口)

package com.lee.java;

/**
 * 创建多线程的方式二:实现Runnable接口
 * 1.创建一个实现了Runnable接口的类
 * 2.实现类去实现Runnable中的抽象方法:Run()
 * 3.创建Thread类的子类的对象
 * 4.通过此对象调用start()
 * @author Lee
 * @create 2021-08-15 22:49
 */

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 ThreadTest1 {
    public static void main(String[] args) {
        //3. 创建实现类的对象(共用)
        MThread mThread = new MThread();
        //4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread t1 = new Thread(mThread);
        t1.setName("线程1");
        //5. 通过Thread类的对象调用start():① 启动线程 ②调用当前线程的run()-->调用了Runnable类型的target的run()
        t1.start();

        //再启动一个线程
        Thread t2 = new Thread(mThread);
        t2.start();
    }
}

1.6.4 两者对比

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

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

1.7 Thread类的方法

?重写方法抛出的异常不能比原来的更大

1.8 线程的优先级

?优先级高并不意味着先执行,高概率先执行。

package com.lee.java;

/**
 *
 *
 * @author Lee
 * @create 2021-08-12 22:34
 */
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() + ":" + Thread.currentThread().getPriority() + ":" +i);
            }

            if (i % 10 == 0) {
                this.yield();//this是当前类的对象,即当前线程。释放当前cpu的执行权
//                Thread.currentThread().yield();//和上面的写法等价
            }
        }
    }

    //利用构造器命名
    public HelloThread(String name){
        super(name);
    }
}

public class ThreadMethodTest {
    public static void main(String[] args) {

        
        //给子线程起名+运行
//        1.构造器命名
        HelloThread h1 = new HelloThread("线程1");

//        2.setname 命名
//        HelloThread h1 = new HelloThread();
//        h1.setName("线程1");
        h1.start();

//        3.设置线程的优先级
        h1.setPriority(Thread.MAX_PRIORITY);
        //给主线程起名
        Thread.currentThread().setName("主线程");
        //给主线程设置优先级
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

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


        }
    }

}

1.9 线程的分类

一种是守护线程,一种是用户线程。

2 多窗口卖票

2.1 使用继承Thread类的方式

package com.lee.java;

/**
 * 例子:创建三个窗口卖票,总票数为100张
 * @author Lee
 * @create 2021-08-13 22:27
 */

class Window extends Thread {
//    private int ticket = 100;//每个对象有自己的100张票
    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            if (ticket > 0){
                System.out.println(getName() + ":卖票,票号为:" + ticket);
                //三个窗口同时在卖第100张票
                ticket--;
            } else {
                break;
            }
        }
    }
}
public class WindowTest {
    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.3 使用实现Runnable接口的方式(p)

package com.lee.java;

/**
 * @author Lee
 * @create 2021-08-15 23: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 w1 = new Thread(w);
        Thread w2 = new Thread(w);
        Thread w3 = new Thread(w);

        w1.start();
        w2.start();
        w3.start();

    }
}

2.4 接口方法更好

单继承只能继承一个父类

继承的方式中,要设置static变量

?* 比较创建线程的两种方式。
?* 开发中:优先选择:实现Runnable接口的方式
?* 原因:1. 实现的方式没有类的单继承性的局限性
?* ? ? ?2. 实现的方式更适合来处理多个线程有共享数据的情况。
?*
?* 联系:public class Thread implements Runnable

继承Thread,Thread实现Runnable。为何不直接实现Runnable。
?* 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:15:56  更:2021-08-17 15:16:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 21:40:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码