java 多线程

  在了解线程之前,要先了解进程,进程,就是正在运行中的程序,你可能已经见过进程。按ctrl +alt + del 启动任务管理器,它有一个选项卡就是进程,点击一下,确实是电脑中正在运程的程序。当一个应用程序启动后,比如QQ, 它就会在内存中开辟一片空间,这片空间就是进程。启动后,程序就要进行执行,执行的就是线程。线程就是进程中控制程序执行的一个控制单元。线程只是一片内存中的空间,它不负责程序执行。负责程序执行的是线程。一个进程中可以有多个线程,这就叫多线程。360安全卫士就是一个多线程。当我们启动360以后,它就会在内存中开发辟一片空间,Windows 资源管理器中多了360,但它什么都没有做,仅仅是启动了一个程序。 当我点击立即体验时,可以看到正在体验,这时再点击电脑清理,它会发现电脑正在进行清理,这两个功能在同时执行,但是都在一个程序中,这两个功能就是线程,我们可以同时启动多个线程。线程是负责程序执行。多线程的启动,就是为了运行各自的内容,这个内容可以称之为多线程执行的任务。

  多线程,其实是cpu在各个程序的各个线程中进行快速的切换,执行代码,由于切换非常快,给我们错觉是各个程序在同时执行。如果太多的多线程在同时执行,cpu在各个线程中来回切换的频率就会变小,电脑有时就很卡。 一个解决办法,就是增加cpu,这就是电脑2核,4核的由来。一个核执行一个程序,那就是真正同时运行。但是如果开多个程序,还是有问题。因为一个是内存不足,二是,线程切换确实消耗资源。这也是多线程的弊端。

   java 中创建多线程要用到Thread类,并且它的步骤如下

  1, 定义一个子类继承Thread 类

  2,覆盖Thread 类的run 方法。我们开启线程的目的就是执行一段代码,一个任务,我们定义了线程,如果它没有任务执行,也没有什么用。线程 执行的任务就是写在run 方法中。我们开启这个线程要做什么事情,就写到定义的子类的run方法中。

  3,创建子类的对象

  4,调用对象的start的方法 开启线程,调用run方法,执行任务

public class ComputeArea {
    public static void main(String[] args) {
        
        // 利用ChildThread子类创建子类对象
        ChildThread c1 = new ChildThread("firstThread");
        ChildThread c2 = new ChildThread("second");
        
        // 调用子类对象的start方法开启线程,执行任务
        c1.start();
        c2.start();
    }

}
// 定义一个子类 继承Thread 类
class ChildThread extends Thread {
    
    private String name;
    
    public ChildThread(String name) {
        this.name = name;
    }
//    复写Thread 类的run方法, 在run方法中定义线程要执行的任务
    public void run() {
        for (int i = 0; i < 10000; i++) {
            if (i % 100 == 0) {
                System.out.println(name);
            }
        }
    }
}

  开启多线程之后,我们怎么才能知道当前执行线程是哪个线程? Thread 类提供了一个静态方法currentThread() 就是返回当前执行线程的引用,再调用getName()方法,就可以获取到。把上面的System.out改成下面代码

System.out.println(name + Thread.currentThread().getName());

   创建多线程的第二种方式是,实现Runnable 接口,覆写其中的run 方法,我们多线程要执行的代码写在run 方法中。我们写一个Demo类来实现Runnable接口,覆盖的run方法中书写要执行的任务

class Demo implements Runnable {

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

  我们定义了一个Demo 类,覆写了run 方法。我们就是定义了一个线程任务。现在需要开启线程, 执行这个任务, 需要分为三个步骤

  1,创建Runnable接口的子类对象,在这里就是Demo 对象,Demo d = new Demo()

  2,然后创建一个线程对象,就是一个Thread 类对象 ,Thread 类的构造函数要接受一个参数,就是我们创建的Demo 对象d;Thread t1 = new Thread(d);

  3, 线程对象 t1 执行start方法,开启线程。

public class ThreadDemo {
    
    public static void main(String[] args) {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
    }

}

   在继续学习多线程之前,要先了解一下线程的生命周期, 一般来说,线程有5种状态(state): new(创建), runnable(可运行状态), running (正在运行的状态),blocked(阻塞状态), dead(死亡状态)

  1,new state: 当我们创建一个线程对象的时候,这个线程就已经产生了,也就进入了创建阶段,就是执行完了  Thread t1 = new Thread(d); 语句, t1 线程产生,进行了创建阶段。这时线程并没有被安排执行(not yet scheduled for running), 因此在这种情下,我们只能做两件事情: 或安排它执行(调用start() 方法), 或直接杀死它(调用stop() 方法)。 如果调用start()方法,线程进入到了runnable 状态。注意,创建状态下,不能调用其它方法,否则会抛出异常。

  2,runnable, 可执行状态,就是执行t1.start() 之后。当线程进入到runable 状态以后,它就表示可以执行了,然后等待cpu 来执行它,也就是说,线程进入了线程队列中,等待执行。如果这个线程和其它线程一样,有相同的优先级,它就会被随机分配时间来执行,所有的线程都会轮流获取到时间来执行。The runnable state means that the thread is ready for execution and is waiting for the availability of the processor. That is, the thread has joined the queue of threads that are waiting for execution. If all threads are of equal priority, then they are given time slots for execution in round robin fashion(轮流).

  3, running: 正在运行的状态,这个很好理解,就是cpu 正在执行这个线程。线程在这个阶段,可以放弃它的执行,然后再加入到线程队列中,等待执行,也就是说进入到了runable 状态。The thread that relinquishes(放弃) control joins the queue at the end and again waits for its run. However, if we want a thread to relinquish control to another thread of equal priority before its turn comes, it can do so by invoking the yield() method.

  4,blocked 状态,阻塞状态,这个在我们上面的代码中没有体现。一个线程不能够进入到runnable 状态,进而进入到running 状态,也就意味着,这个线程进入到了blocked 状态。为什么会出现这种情况呢?可能是需要等待其它线程的结果之类的。注意,blocked 状态不是dead 状态,它完全具备重新执行的能力。A thread is said to be blocked when it is prevented form entering into the runnable state and subsequently the running state. This happens when the thread is suspended, sleeping or waiting in order to satisfy certain requirements. A blocked thread is considered ‘not ruunable ’ but not dead and therefore fully qualified to run again.

  5, dead 死亡状态,当一个线程执行完之后,它自然进入到死亡状态,因为它的使命已经完成了。当然,我们也可以直接杀死它。不管是在创建的候,还是在运行的时候,甚至在阻塞的时候。However, we kill it by sending the stop message to it at any state thus causing a premature death. A thread can be killed as soon as it is born, or while it is running, or even when it is in ‘not runnable’(blocked condition)

原文地址:https://www.cnblogs.com/SamWeb/p/8099567.html