1、进程与线程

(1)进程(Process):“正在执行的程序”,程序进入内存运行就变成了一个进程。一个进程会产生多个线程。

(2)多线程(Multithread):一个进程中同时存在几个执行体。单线程是按照函数的顺序执行,多线程是多段代码同时交替运行。CPU的一个核,在某一时刻只能执行一个线程,CPU在多个线程之间快速地切换。

(3)线程的调度:分时和抢占。分时调度是预先分配每个线程的时间。抢占式调度是按优先级。

(4)资源与调度

进程:

   进程是操作系统分配资源的最小单元

 线程:

   线程本身拥有少量资源,它可以共享所属进程的资源

   线程是操作系统调度的最小单元

(5)默认有两个进程:main进程和GC进程

进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元。
一个程序至少有一个进程,一个进程至少有一个线程。

 

2、多线程的实现

(1)方式一:继承Thread类

public class MyThread extends Thread{       //继承自Thread类

    public MyThread(String name) {          //调用父类的构造方法
        super(name);
    }
    public void run() {                     //重写run方法,线程需要执行的代码放在run方法内
        for (int i = 0; i < 20; i++) {
            System.out.println(getName()+":正在执行!"+i);//Thread.currentThread().getName();获取当前线程对象的名称
        }
    }


}
public class Test {
public static void main(String[] args) {
    MyThread mt = new MyThread("我的线程");
    mt.start();
    for (int i = 0; i < 20; i++) {
        System.out.println("主函数线程!"+i);
    }
    System.out.println("主函数执行结束了");
}
}

多线程(进程与线程、多线程的实现方式、线程池、多线程的优点)_单线程

由运行结果可知,两个线程的运行顺序由线程抢占到的CPU资源而定。

 Thread.currentThread()获取当前线程对象

 Thread.currentThread().getName();获取当前线程对象的名称

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

(2)方式二:实现Runable接口

以实现Runable接口的方式创建线程比继承Thread类有很大的优越性,因为类不能多重继承,即一个类只能继承一个类,那么如果该类已经继承了一个类,就不能实现多线程了,但是可以通过实现Runable接口的方式实现多线程。

Runnable实现多线程:

package pers.zhb.runnable;

public class MyThread implements Runnable{

    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+":正在执行!"+i);
        }
        
    }

}
package pers.zhb.runnable;

public class RunnableDemo {
public static void main(String[] args) {
    MyThread mt=new MyThread();
    Thread  t2=new Thread(mt);//Thread类本质上也是实现了Runnable接口,但是Run方法是空的
    t2.start();
    for (int i = 0; i < 20; i++) {
        System.out.println("主函数线程!"+i);
    }
    System.out.println("主函数执行结束了");
    
}
}

(3)join()方法的使用

join()方法的作用是使线程串行化,如在线程B中调用线程A的join方法,则线程A执行完后线程B再执行

package pers.zhb.runnable;

public class MyThread implements Runnable{

    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+":正在执行!"+i);
        }
        
    }

}
package pers.zhb.runnable;

public class RunnableDemo {
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread t1 = new Thread(mt);

        t1.start();

        t1.join();

        for (int i = 0; i < 20; i++) {
            System.out.println("主函数线程!" + i);
        }

        System.out.println("主函数执行结束了");

    }
}

多线程(进程与线程、多线程的实现方式、线程池、多线程的优点)_单线程_02

 主线程在子线程运行结束后才开始运行。

 

3、线程池

(1)概念

  我们用两种方式创建的线程,在使用后都会被销毁,频繁地创建和销毁会造成时间和资源的浪费。线程池是一个能够容纳多个线程的容器,里面的线程可以反复使用。线程是稀缺资源,它的创建与销毁是一个相对偏重且耗资源的操作,而Java线程依赖于内核线程,要进行操作系统状态切换,为避免资源过度消耗需要设法重用线程执行多个任务。线程池就是一个负责对线程进行统一分配、调优与监控。

public class MyThread implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class RunnableDemo {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(3);
        // Executors:线程池创建工厂类,调用方法返回线程池对象
        es.submit(new MyThread());
        es.submit(new MyThread());
        es.submit(new MyThread());
    }
}

多线程(进程与线程、多线程的实现方式、线程池、多线程的优点)_i++_03

(2)使用

  • 单个任务处理时间比较短
  • 需要处理的任务数量很大

(3)优点

  • 重用存在的线程,减少线程创建,消亡的开销,提高性能。我们用创建的线程,在使用后都会被销毁,频繁地创建和销毁会造成时间和资源的浪费。
  • 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。线程池是一个能够容纳多个线程的容器,里面的线程可以反复使用。
  • 提高线程的可管理性,可统一分配,调优和监控

 

4、多线程的优点

(1)充分利用CPU资源

  在单线程的程序中,如果线程被阻塞程序就不能执行,因为它们是顺序执行的。而在多线程程序中,如果一个线程被阻塞了别的线程就可以利用CPU资源。也就是说CPU一直处于忙碌的状态。在有读写操作的系统中,当处于读写操作的时候不需要CPU资源,只有计算的时候才需要,如果是单线程执行,CPU就会有一段时间处于空闲状态,多线程的话CPU就能一直处于忙碌状态,提高了CPU的利用率。

(2)简化编程模型

手机游戏中既有背景音乐又有画面等功能,这些功能是并行的,如果利用单线程只能按照顺序执行,但是运用多线程的知识就可以很容易地实现

 

每个人都会有一段异常艰难的时光 。 生活的压力 , 工作的失意 , 学业的压力。 爱的惶惶不可终日。 挺过来的 ,人生就会豁然开朗。 挺不过来的 ,时间也会教你 ,怎么与它们握手言和 ,所以不必害怕的。 ——杨绛