Java中的线程

2023-11-16

一.程序,进程,线程之间的关系

程序、进程和线程是计算机中重要的概念,它们描述了不同层次上的执行和管理方式。

程序是指由一系列指令组成的代码文件,它定义了算法和逻辑,用来解决特定的问题。程序本身是静态的,只有在被加载到内存并被操作系统调度执行时才会动起来。

进程是程序在执行时的一个实例,它是操作系统进行资源管理和调度的基本单位。一个进程拥有独立的内存空间和系统资源,包括打开的文件、网络连接等。进程之间相互独立,一个进程的崩溃不会影响其他进程的运行。

线程是进程内的独立执行单元,一个进程可以有多个线程。线程共享相同的内存空间和系统资源,可以与其他线程共享数据。相对于进程来说,线程的创建和销毁更加轻量级,切换和通信的开销也较小。

三者关系:一个程序在执行时被操作系统加载成一个进程,进程中可以有多个线程并行执行。程序是静态的,进程和线程是动态的执行状态。进程和线程通常是并发执行的,它们的执行顺序和并发性由操作系统的调度算法决定。不同的操作系统可能有不同的调度策略。同时,进程和线程是操作系统资源的消耗者。每个进程都有自己独立的内存空间和系统资源,而线程则共享进程的资源。因此,正确的管理进程和线程,合理分配资源,能够提高系统的性能和稳定性。

二.线程

2.1如何创建线程

在Java中,你可以通过两种方式创建线程:

继承Thread类:创建一个继承自Thread类的子类,重写run()方法,并在run()方法中定义线程的任务逻辑。然后实例化子类对象,并调用start()方法来启动线程。

以下是一个使用继承Thread类创建线程的示例代码:

public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程任务逻辑
        System.out.println("线程任务逻辑");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}

实现Runnable接口:创建一个实现了Runnable接口的类,实现run()方法,并在run()方法中定义线程的任务逻辑。然后实例化该类对象,并将其作为参数传递给Thread类的构造方法。再调用start()方法来启动线程。

以下是一个使用实现Runnable接口创建线程的示例代码:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程任务逻辑
        System.out.println("线程任务逻辑");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start(); // 启动线程
    }
}

无论使用哪种方式创建线程,都需要调用start()方法来启动线程。线程启动后,会自动调用run()方法来执行线程任务。

三.线程中的常用方法

线程中有一些常用的方法,以下是其中一些常见的方法:
(1)start()方法:用于启动线程。调用该方法后,线程会被放入就绪队列,等待获取CPU的执行权。
(2)run()方法:线程的主体代码逻辑通常在run()方法中实现。该方法定义了线程的任务。
(3)sleep(long millis)方法:让当前线程暂停执行一段时间,单位为毫秒。在暂停期间,线程状态不会变为阻塞或就绪状态,而是保持运行状态。
(4)join()方法:等待调用该方法的线程执行完毕后再继续执行其他线程。可以通过传入参数指定最长等待时间。
(5)yield()方法:让出当前线程的CPU执行权,使得其他具有相同优先级的线程有机会执行。yield方法只是让当前线程重新回到可运行状态,而不是阻塞状态。
(6)setName():为线程设置名字。

(7)currentThread():获取当前线程。

(8)getName():获取当前线程的名字。

(10)setPriority():设置线程的优先级(从一到十,默认是5)。

         MAX_PRIORITY:取值为10,表示最高优先级。 

         MIN_PRIORITY:取值为1,表示最底优先级。

        NORM_PRIORITY:取值为5,表示默认的优先级

(11)getPriority():获取当前线程的优先级。

(12)setDaemon():设置守护线程。

线程中常用方法的具体实现:

public class Mythread1 extends Thread{
    //创建线程首先要继承Thread
    //重写run方法

    @Override
    public void run() {
        //将需要执行的代码放在run方法当中
        for (int i = 0; i < 1000; i++) {
            if (i%2==0){//获取0-1000之间的偶数
                System.out.println("MyThread:"+i);
            }
        }
    }
}
    public static void main(String[] args) {
        //main函数相当于是主线程
        //创建子线程对象
        Mythread1 mythread1 = new Mythread1();
        //切记不能直接调用子线程中的run方法,那就相当于是直接调用方法,不是启动子线程
        //mythread1.run();
        mythread1.start();//启动子线程
        for (int i = 0; i < 1000; i++) {
            if(i%2==1){//main函数让其输出奇数,区分
                System.out.println("main:"+i);
            }
        }
    }

  在这个代码中,在main函数中创建了一个线程,一个线程执行的是输出偶数,一个是偶数。这段代码运用的方法有start()。                              

public class MyRunnnable1 implements Runnable{
    //Runnable接口,要重写run方法
    //run方法中写的是要执行的逻辑(代码)
    @Override
    public void run() {
        for (int i = 0; i <1000; i++) {
            System.out.println(Thread.currentThread().getName()+i);
            //Thread.currentThread().getName()调用此线程的名字
        }
    }
}
    public static void main(String[] args) {
        //创建Runnable接口的对象
        MyRunnnable1 myRunnnable = new MyRunnnable1();//创建了一个线程中执行的任务
        Thread thread = new Thread(myRunnnable);//此处才是创建了一个线程
        thread.setName("Run线程");
        System.out.println(thread.getName());//获取线程的名字
        System.out.println(thread.getId());//获取线程的id
        thread.setPriority(10);//设置线程优先级,默认为 5,优先级的范围是(1-10)
        thread.start();//启动线程
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
        System.out.println(thread.getPriority());//获取线程优先级
        System.out.println(Thread.currentThread().getPriority());//获取当前线程的优先级
    }

这里的两段代码是创建线程的另外一种方式。实现的是Runnable接口。

public class MyThreadDemo extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5000; i++) {
            if (i%50==0){
                MyThreadDemo.yield();//让出自己所占用的内存
            }
            System.out.println("MyThread:"+i);
        }
    }
}
    public static void main(String[] args) {
        MyThreadDemo myThreadDemo = new MyThreadDemo();
        myThreadDemo.start();
        for (int i = 0; i < 4000; i++) {
                System.out.println("main:"+i);
        }
    }

在这两段代码中用到了yeild()方法,这个方法的作用是让出自己所占用的线程。

public class MyThread extends Thread{
    //测试join
    @Override
    public void run() {
        for (int i = 0; i < 101; i++) {
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
}
    public static void main(String[] args) throws InterruptedException {
        MyThread thread = new MyThread();
        thread.setName("xx");
        thread.join();//让其他线程等待此线程结束
        thread.start();

        MyThread thread1 = new MyThread();
        thread.setName("dd");
        thread1.start();
    }

这两段代码测试的是join的功能,等待调用该方法的线程执行完毕后再继续执行其他线程。

public class DeamonThread extends Thread {
    //测试守护线程
    @Override
    public void run() {
        int n = 0;
        while (true){
            System.out.println(Thread.currentThread().getName()+":"+n++);
        }
    }
}
    public static void main(String[] args) {
        DeamonThread deamonThread = new DeamonThread();
        deamonThread.setDaemon(true);//设置此线程为守护线程
        deamonThread.start();
        for (int i = 0; i <1000 ; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }

这两段代码测试的是设置守护线程,守护线程就是只要当前JVM实例中尚存在 任何一个非守护线程没有结束,守护线程就全部工作。

以下两段是为了展示同步锁(sychronized)的功能:

public class PiaoThread extends Thread{
    static int num = 10;
    @Override
    public void run() {
        while(true){
            this.Buy();
        }
    }
    /*synchronized 修饰方法有两种情况:
    1.当修饰的是非静态方法时候,锁的对象是this
    2.当修饰的是静态的方法时,锁的对象是该类的class对象
    */

    public synchronized static void Buy(){
        if(num>0){
            System.out.println(Thread.currentThread().getName()+":"+num);
            num--;
        }
    }
}
    public static void main(String[] args) {
        PiaoThread piaoThread = new PiaoThread();
        piaoThread.setName("窗口一");
        piaoThread.start();
        PiaoThread piaoThread1 = new PiaoThread();
        piaoThread1.setName("窗口二");
        piaoThread1.start();

    }

设置同步锁之后,同步锁中的代码在同一时间只有一个线程可以进来。

如上两段代码的结果如下:

以下两段代码是上两段代码的Runnable接口的实现方式:

public class PiaoRun implements Runnable{
    int num = 10;
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.buy();
        }
    }
    public synchronized void buy(){
        if(num>0){
            System.out.println(Thread.currentThread().getName()+":"+num);
            num--;
        }
    }
}
    public static void main(String[] args) {
        PiaoRun piaoRun = new PiaoRun();
        Thread t1 = new Thread(piaoRun,"窗口一");
        Thread t2 = new Thread(piaoRun,"窗口二");
        t1.start();
        t2.start();
    }

 这两段代码就是Runnable接口的实现方式。

public class LockThread extends Thread{
    static int num = 10;
    static Lock lock = new ReentrantLock();
    /*ReentranLock 和 synchronized的区别
    *1.Lock 是一种Java代码底层的控制实现 ,synchronized是关键字,不依赖与Java代码,依赖与底层指令
    *2.ReentranLock只能对一段代码进行加锁,而synchronized既可以修饰方法,又可以修饰属性
    *3.Lock要自己主动加锁和释放锁,synchronized会自动加锁和释放锁
    * */
    @Override
    public void run() {
        while(true){
            //启动锁
            lock.lock();
            try {
                Thread.sleep(20);
                if(num>0){
                    System.out.println(Thread.currentThread().getName()+":"+num);
                    num--;
                }else {
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();//关闭锁
            }
        }
    }
}
    public static void main(String[] args) {
        LockThread lockThread = new LockThread();
        Thread t1 = new Thread(lockThread,"窗口一");
        Thread t2 = new Thread(lockThread,"窗口二");
        t1.start();
        t2.start();
    }

以上两段代码是另外一种给代码加锁的方式。

public class SiThread extends Thread{
    Boolean b = null;
    static Object objA = new Object();
    static Object objB = new Object();
    public SiThread(Boolean b) {
        this.b = b;
    }
    @Override
    public void run() {
        if(b){
            synchronized(objA){
                System.out.println("if-objA");
                synchronized(objB){
                    System.out.println("if-objB");
                }
            }
        }else{
            synchronized (objB){
                System.out.println("else-objB");
                synchronized (objA){
                    System.out.println("else-objA");
                }
            }
        }
    }
}
    public static void main(String[] args) {
        SiThread siThread1 = new SiThread(true);
        SiThread siThread2 = new SiThread(false);
        siThread1.start();
        siThread2.start();
    }

以上的两段代码就是所谓的死锁,两段代码都在等待对方正在运行的线程,但是都不放手,就会造成死锁,同时程序也不会停止,结果如下:

public class WaitThread extends Thread{
    static Object object = new Object();
    static int num = 1;
    @Override
    public void run() {
        while (num<=100){
            synchronized (object){
               object.notify();//唤醒被wait的线程,优先优先级高的线程
                System.out.println(Thread.currentThread().getName()+":"+num);
                num++;
                try {
                    object.wait();//调用此方法会让当前正在执行的线程进入阻塞状态,并释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
    public static void main(String[] args) {
        WaitThread waitThread1 = new WaitThread();
        WaitThread waitThread2 = new WaitThread();
        waitThread1.start();
        waitThread2.start();
    }

以上这两段代码就是Object类中的notify和wait方法,一个是让线程处于阻塞状态,释放当前锁,一个是唤醒被wait的线程,如果有多个被wait的线程,首先唤醒优先级最高的一个。notifyall()此方法式用于唤醒全部被wait的方法。

注意:这三个方法必须处在同步代码块中。

四.多线程

4.1多线程的概念

多线程是指在一个程序中同时运行多个线程,每个线程都可以独立执行不同的任务或代码片段。与传统的单线程程序相比,多线程能够充分利用计算机的多核处理器和资源,并提高程序的并发性和响应性。在多线程环境下,每个线程都有自己的执行路径和执行状态,并且可以独立地进行操作和执行代码块。不同线程之间可以并行执行,从而实现同时处理多个任务、提高系统吞吐量和资源利用率。

4.2多线程的优缺点

多线程编程有以下优点和缺点:

优点:

  1. 提高程序的响应性:多线程可以将耗时的操作放在后台线程中执行,使得主线程可以及时响应用户的输入和请求,提升程序的交互性和用户体验。
  2. 提高系统资源利用率:通过并行执行多个任务,充分利用多核处理器或多CPU的计算能力,加快任务处理速度,提高系统的吞吐量和资源利用效率。
  3. 改善程序设计结构:使用多线程可以将复杂的任务拆分成多个独立的子任务,并发地进行处理,使程序的结构更清晰、模块化,便于维护和扩展。

缺点:

  1. 多线程编程复杂性高:线程之间的并发操作存在数据共享和同步等问题,需要合理地设计和管理线程之间的协作和数据同步,对开发人员要求较高,容易出现各种并发问题,如死锁、竞态条件等。
  2. 资源占用和调度开销:每个线程都会占用一定的内存空间和CPU调度开销,当线程数量过多时,会增加系统的负担,甚至导致系统资源的不足和性能下降。
  3. 可能引发安全问题:多线程程序在处理共享数据时需要正确地进行同步操作,否则可能会引发数据不一致、并发访问冲突等线程安全问题,增加了程序设计和调试的复杂性。

因此,在使用多线程编程时,需要仔细权衡其优点和缺点,并合理设计和管理多线程的使用,以避免潜在的问题和风险。

4.3线程同步

线程同步是指多个线程之间协调和同步彼此的行为,以保证它们按照预期的顺序执行和访问共享资源,避免出现并发操作导致的数据不一致、竞争条件等问题。

并发与并行:

 并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。

并发:在一个时间段内一次执行操作.例如卖票,抢购,秒杀看似同时进行, 实际是一个一个执行。

多线程同步:

 多个线程同时读写同一份共享资源时,可能会引起冲突。所以引入线程“同步”机制, 即各线程间要有先来后到;

同步就是排队+锁:

几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行操作;为了保证数据在方法中被访问时的正确性,在访问时加入锁机制。

 4.4线程通信

线程通信是指多个线程之间进行信息交换、数据传递或协调操作的过程。在多线程编程中,不同的线程可能需要共享数据、协调执行顺序或进行协作任务,因此需要一种机制来实现线程之间的交互和通信。

常见的线程通信方式包括:

  1. 共享内存:多个线程通过访问共享内存区域来进行数据共享。线程可以读取和修改共享内存中的数据,但需要注意线程安全性和同步问题,以避免竞态条件或数据不一致的情况发生。

  2. 互斥锁(Mutex):通过互斥锁来保护共享资源的访问,确保同一时间只有一个线程能够操作共享资源。当一个线程获取到互斥锁时,其他线程需要等待,直到该线程释放锁。

  3. 条件变量(Condition Variable):线程可以使用条件变量进行等待和唤醒的操作。一个线程可以在满足特定条件之前等待,并在其他线程满足条件后发出信号通知等待线程继续执行。

  4. 信号量(Semaphore):通过信号量来控制对资源的访问数量。信号量可以用于限制同时访问某个资源的线程数量,或者在某个事件满足时发出通知。

  5. 消息队列(Message Queue):线程之间可以通过消息队列发送和接收消息。一个线程可以将消息放入队列中,另一个线程则从队列中获取消息进行处理。

  6. 管道(Pipe):管道是一种单向的通信机制,可用于实现两个线程之间的通信。一个线程将数据写入管道的写端口,另一个线程则从管道的读端口读取数据。

这些线程通信方式可以根据具体需求和场景进行选择和组合使用,以实现线程之间的协作和信息交换。在实际应用中,需要注意线程安全性、同步问题和避免死锁等相关技术细节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中的线程 的相关文章

  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • Java:扩展类并实现具有相同方法的接口

    可能无法完成以下操作 我收到编译错误 继承的方法 A doSomthing int 无法隐藏 B 中的公共抽象方法 public class A int doSomthing int x return x public interface
  • Java Logger 未记录到 Netbeans 中的输出

    我正在 Netbeans 中使用 Maven 启动一个 Java 项目 我编写了一些代码来使用 Logger 类进行日志记录 但是 日志记录似乎不起作用 在程序开始时 我运行 Logger getLogger ProjectMainClas
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • 如何在 JPQL 或 HQL 中进行限制查询?

    在 Hibernate 3 中 有没有办法在 HQL 中执行相当于以下 MySQL 限制的操作 select from a table order by a table column desc limit 0 20 如果可能的话 我不想使用
  • 将巨大的模式编译成Java

    有两个主要工具提供了将 XSD 模式编译为 Java 的方法 xmlbeans 和 JAXB 问题是 XSD 模式确实很大 30MB 的 XML 文件 大部分模式在我的项目中没有使用 所以我可以注释掉大部分代码 但这不是一个好的解决方案 目
  • 如何在单个查询中搜索 RealmObject 的 RealmList 字段

    假设我有一堂课 public class Company extends RealmObject private String companyId private RealmList
  • 如何在 Spring 中使 @PropertyResource 优先于任何其他 application.properties ?

    我正在尝试在类路径之外添加外部配置属性资源 它应该覆盖任何现有的属性 但以下方法不起作用 SpringBootApplication PropertySource d app properties public class MyClass
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • 如何仅从 Firestore 获取最新更新的数据?

    在 Firestore 上发现任何更改时始终获取整个文档 如何只获取最近更新的数据 这是我的数据 我需要在第一次加载时在聊天中按对象顺序 例如 2018 09 17 30 40 msg和sendby 并且如果数据更新则仅获取新的msg和se
  • Jetty、websocket、java.lang.RuntimeException:无法加载平台配置器

    我尝试在 Endpoint 中获取 http 会话 我遵循了这个建议https stackoverflow com a 17994303 https stackoverflow com a 17994303 这就是我这样做的原因 publi
  • 如何将 HTML 链接放入电子邮件正文中?

    我有一个可以发送邮件的应用程序 用 Java 实现 我想在邮件中放置一个 HTML 链接 但该链接显示为普通字母 而不是 HTML 链接 我怎样才能将 HTML 链接放入字符串中 我需要特殊字符吗 太感谢了 Update 大家好你们好 感谢
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • 在 Java 中获取并存储子进程的输出

    我正在做一些需要我开始子处理 命令提示符 并在其上执行一些命令的事情 我需要从子进程获取输出并将其存储在文件或字符串中 这是我到目前为止所做的 但它不起作用 public static void main String args try R
  • 如何区分从 Saxon XPathSelector 返回的属性节点和元素节点

    给定 XML
  • Java Swing - 如何禁用 JPanel?

    我有一些JComponents on a JPanel我想在按下 开始 按钮时禁用所有这些组件 目前 我通过以下方式显式禁用所有组件 component1 setEnabled false 但是有什么办法可以一次性禁用所有组件吗 我尝试禁用
  • 为什么\0在java中不同系统中打印不同的输出

    下面的代码在不同的系统中打印不同的输出 String s hello vsrd replace 0 System out println s 当我在我的系统中尝试时 Linux Ubuntu Netbeans 7 1 它打印 When I
  • 使用 HtmlUnit 定位弹出窗口

    我正在构建一个登录网站并抓取一些数据的程序 登录表单是一个弹出窗口 所以我需要访问这个www betexplorer com网站 在页面的右上角有一个登录链接 写着 登录 我单击该链接 然后出现登录弹出表单 我能够找到顶部的登录链接 但找不
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro

随机推荐

  • 从Kubernetes 1.14 发布,看技术社区演进方向

    Kubernetes 1 14 正式发布已经过去了一段时间 相信你已经从不同渠道看过了各种版本的解读 不过 相比于代码 Release 马上就要迎来5周岁生日的Kubernetes 项目接下来如何演进 其实也是一个让人着迷的话题 而作为一个
  • 在linux中,&和&&,

    对应刚接触linux命令的小伙伴们来说 这些符号一定是很困扰的下面我们一起来看这些符号区别和用法 表示任务在后台执行 如要在后台运行 如 root localhost local java jar test jar gt log txt 运
  • 大型 SaaS 平台产品架构设计

    当我们去搜索 架构 可以得到很多的架构图片 比如组织架构 业务架构 数据架构 技术架构 安全架构 产品架构 部署架构等 什么是架构 通常大家说架构一般指软件架构 架构是指软件的基础结构 创造这些基础结构的准则 以及对这些结构的描述 在这个定
  • IAR常见报错

    右键进入函数出错 project gt clean
  • 利用python进行数据分析之数据聚合和分组运算--小白笔记

    GroupBy机制 split apply combine 拆分 应用 合并 import pandas as pd import numpy as np df pd DataFrame key1 a a b b a key2 one tw
  • 找不到匹配的host key算法

    vim etc ssh sshd config
  • 《WebRTC系列》实战 Web 端支持 h265 硬解

    1 背景 Web 端实时预览 H 265 需求一直存在 但由于之前 Chrome 本身不支持 H 265 硬解 软解性能消耗大 仅能支持一路播放 该需求被搁置 去年 9 月份 Chrome 发布 M106 版本 默认开启 H 265 硬解
  • raw格式详解

    raw格式是camera sensor直接输出的格式 每个像素点表示一个颜色分量B G或R 注意 这句话不准确 红外相机的sensor和彩色相机的sensor有些不同 有的红外相机的sensor输出的raw data就是亮度值 即灰度值 输
  • Android Flutter开发环境搭建

    1 搭建 Flutter 开发环境 本栏亦在快速上手Android Flutter Flutter框架就不介绍了 框架这个东西怎么说呢 对于大部分人来说只是了解即可 如需了解的话 可以度娘资料很多 本节我们主要看下如何在Windwos下搭建
  • Kotlin协程实现原理:CoroutineScope,看完不懂你砍我!墙裂建议收藏。

    今天我们来聊聊Kotlin的协程Coroutine 文末有为大家准备的彩蛋 如果你还没有接触过协程 推荐你先阅读这篇入门级文章What 你还不知道Kotlin Coroutine 如果你已经接触过协程 相信你都有过以下几个疑问 协程到底是个
  • 一个码稿人自述:什么样的文档产品适合我?|深度吐槽

    关注ITValue 看企业级最新鲜 最价值报道 图片来源 Unsplash 钛媒体打工人 媒体相关从业经验4 5年 文档使用重度患者 今天以我曾经用过的 和现在主流的一些文档产品为例 来谈谈我的使用体验 以及什么样的文档适合我 一 我与文档
  • [编程工具]MarkDown编辑查看以及使用语法

    目录 0 前言 1 markDown语法 2 markDown 3 MD正确打开方式 4 结尾 结束啦感谢观看 5 参考连接 0 前言 本文介绍了markDown的编辑查看 使用浏览器查看以及Vscode中查看编辑MD 最后介绍了MD的常用
  • python解析佳明fit文件

    使用 fitparse 解析 佳明 fit 文件 以下示例测试环境为 python 3 8 fitparse 1 2 fitparse 安装 pip3 install fitparse 使用方式 import fitparse from d
  • 蓝牙通讯

    蓝牙通讯 简介 蓝牙API 所需权限 使用蓝牙的步骤 普通调用案例 通讯案例 简介 蓝牙 是一种支持设备短距离通信 一般10m内 且无阻隔媒介 的无线电技术 能在包括移动电话 PDA 无线耳机 笔记本电脑等众多设备之间进行无线信息交换 利用
  • 数据库创建索引和删除索引的方式总结

    一 创建索引 1 1 使用Alter创建索引 1 添加主键索引 特点 数据列不允许重复 不能为null 一张表只能有一个主键 Mysql主动将该字段进行排序 ALTER TABLE 表名 ADD Primary key col 2 添加唯一
  • MySQL安装与启动

    1 MySQL安装包下载 下载地址 https dev mysql com downloads mysql 这里我的电脑是WIN764位的 大家根据自己的电脑自己选择要下载的包 2 解压安装 解压后进入到Windows的DOS命令行下 切换
  • python股票量化交易系统_利用python建立股票量化交易系统(一)

    从今天开始正式开启我的博客之旅 博客内容全部是我自己的量化心得 主要还是为自己将来中工作之中遇到相似问题 可以方便的找到答案 如果能帮到有相似问题的其他同学 我也很开心 如果帮不到的话 不喜勿喷 如果文章中有什么不对的地方 欢迎批评指正 建
  • VI编辑器的使用常用快捷方式编辑命令

    VI编辑器的使用常用快捷方式编辑命令 一 VI编辑器的工作模式 1 VI编辑器有以下三种工作模式 命令模式 输入模式 末行模式 2 不同模式之间的切换 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img 7BrI0o
  • 【LInux】基础开发工具的使用

    文章目录 一 Linux的应用市场 yum 1 什么是yum 2 为什么要有yum 3 如何使用yum 3 1 前提条件 3 2 搜索软件 3 3 安装软件 3 4 卸载软件 二 Linux的文本编辑器 vim 1 什么是vim 2 为什么
  • Java中的线程

    一 程序 进程 线程之间的关系 程序 进程和线程是计算机中重要的概念 它们描述了不同层次上的执行和管理方式 程序是指由一系列指令组成的代码文件 它定义了算法和逻辑 用来解决特定的问题 程序本身是静态的 只有在被加载到内存并被操作系统调度执行