JAVA基础知识|进程与线程

一、什么是进程?什么是线程?

操作系统可以同时支持多个程序的运行,而一个程序可以狭义的认为就是一个进程。在一个进程的内部,可能包含多个顺序执行流,而每个执行流就对应一个线程。

1.1、进程

进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。当程序进入内存运行时,即为开启了一个进程。

进程的特点:

  • 独立性:进程是系统中独立的实体,可以拥有独立的资源
  • 动态性:进程是动态的,它有自己的生命周期
  • 并发性:多个进程可以并发运行,互不影响

并发性和并行性是不同的概念:并行是指同一时刻,多个命令在多个处理器上同时执行;并发是指在同一时刻,只有一条命令是在处理器上执行的,但多个进程命令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

1.2、线程

线程:是程序内部的顺序执行流。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。线程并不拥有自己的系统资源,它与其他线程一起分享进程的系统资源。

【举例】

public class Test {

    public static void main(String[] args) {
        Thread th = Thread.currentThread();
        System.out.println("Tread name:" + th.getName());
        method();
    }

    public static void method() {
        Thread th = Thread.currentThread();
        System.out.println("Tread name:" + th.getName());
    }
}

执行结果:(当java程序启动的时候,会启动一个由主方法(public static void main(String[] args))所开启的主线程main)

Tread name:main
Tread name:main

执行过程如下:

程序的执行过程:首先把程序的代码放到内存的代码区里面,代码放到代码区后并没有马上开始执行,但这时候说明了一个进程准备开始,进程已经产生了,但还没有开始执行,平常所说的进程的执行指的是进程里面主线程开始执行了,也就是main()方法开始执行了,在我们机器里面实际上运行的都是线程。

二、如何创建多个线程?

2.1、继承Thread类

【举例】

public class MyThread extends Thread {

    private String params;

    public MyThread(String params) {
        this.params = params;
    }

    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        System.out.println(this.params + ":" + thread.getName());
    }
}
public class Test {

    public static void main(String[] args) {
        Thread th = Thread.currentThread();
        System.out.println("main():" + th.getName());
        threadTest1();
        threadTest2();
        method();
    }

    public static void threadTest1() {
        MyThread myThread = new MyThread("threadTest1()");
        myThread.start();
    }

    public static void threadTest2() {
        MyThread myThread = new MyThread("threadTest2");
        myThread.run();
    }

    public static void method() {
        Thread th = Thread.currentThread();
        System.out.println("method():" + th.getName());
    }
}

执行结果:

main():main
threadTest2:main
method():main
threadTest1():Thread-0

 调用myThread.start()方法,会开启一个新的线程Thread-0。而调用run()方法时,不会开启一个新的线程,仍然是单线程模式。

2.2、实现Runnable接口

【举例】

public class MyThread implements Runnable {

    private String params;

    public MyThread(String params) {
        this.params = params;
    }

    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        System.out.println(this.params + ":" + thread.getName());
    }
}
public class Test {

    public static void main(String[] args) {
        Thread th = Thread.currentThread();
        System.out.println("main():" + th.getName());
        threadTest1();
        threadTest2();
        method();
    }

    public static void threadTest1() {
        MyThread myThread = new MyThread("threadTest1()");
        myThread.run();
    }

    public static void threadTest2() {
        MyThread myThread = new MyThread("threadTest2()");
        Thread thread = new Thread(myThread);
        thread.start();
    }

    public static void method() {
        Thread th = Thread.currentThread();
        System.out.println("method():" + th.getName());
    }
}

执行结果:

main():main
threadTest1():main
method():main
threadTest2():Thread-0

实现Runnable接口和继承Thread类这两种开辟新线程的方法,应该优先选择实现Runnable接口。因为接口可以实现多个,而类只能是单继承。

2.3、实现Callable接口

实现Callable接口的好处在于可以获取到线程的返回值,关于Callable和Future,我们会在后面再详细的介绍。

【举例】

public class CallThread implements Callable<Integer> {

    @Override
    public Integer call() {
        int i = 0;
        for (; i < 100; i++) {
            Thread thread = Thread.currentThread();
            System.out.println(i + "\t" + thread.getName());
        }
        return i;
    }
}
public class Test {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CallThread callThread = new CallThread();
        FutureTask<Integer> ft = new FutureTask<>(callThread);
        Thread thread = new Thread(ft);
        thread.start();
        System.out.println("返回值:" + ft.get());
        System.out.println("===============");
        Thread thread1 = Thread.currentThread();
        System.out.println("线程:" + thread1.getName());
    }
}

执行结果:

0    Thread-0
1    Thread-0
2    Thread-0
3    Thread-0
4    Thread-0
5    Thread-0
6    Thread-0
7    Thread-0
8    Thread-0
9    Thread-0
返回值:10
===============
线程:main

虽然程序中打开了两个线程,但是由于需要获取到Thread-0线程的返回值(ft.get()),所以Thread-0线程和main线程并不能并发执行,只有当Thread-0线程执行结束,才可以继续执行main线程。

【修改】

public class Test {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //CallThread callThread = new CallThread();
        //修改为lambda表达式
        FutureTask<Integer> ft = new FutureTask<>(()->{
            int i = 0;
            for (; i < 10; i++) {
                Thread thread = Thread.currentThread();
                System.out.println(i + "\t" + thread.getName());
            }
            return i;
        });
        Thread thread = new Thread(ft);
        thread.start();
        //System.out.println("返回值:" + ft.get());
        System.out.println("===============");
        Thread thread1 = Thread.currentThread();
        System.out.println("线程:" + thread1.getName());
    }
}

执行结果:

===============
0    Thread-0
1    Thread-0
2    Thread-0
3    Thread-0
4    Thread-0
5    Thread-0
6    Thread-0
7    Thread-0
线程:main
8    Thread-0
9    Thread-0

当把“System.out.println("返回值:" + ft.get());”注释掉以后,两个线程就可以并发执行了。

猜你喜欢

转载自www.cnblogs.com/maikucha/p/8884702.html