Java学习(十六)进程与线程入门

操作系统的出现主要是方便于用户与计算机进行交互,管理与分配计算机多项应用程序的资源存储与运行。操作系统最基础的任务是进程的管理,进程是操作系统用于资源分配的最小单位,在一定程度上,我们可以把计算机中应用程序的运行,类似的看做操作系统中的进程的执行。在操作系统中,单核CPU同一时刻只允许一个进程执行,其他进程需要等待。进程在执行中会获得CPU的时间片,这个时间片非常短暂。在不考虑优先级抢占式的情况下,当该进程获取的时间片用完,就会修改当前的执行状态,等待下一次获取时间片的机会。因为操作系统会在毫秒级别的时间进行进程之间的切换,所以好像看起来计算机中QQ聊天、听歌、浏览网页等操作在同时运行。

操作系统除了调度进程的运行之外,还需要给每个新创建的进程分配资源。进程可以当成由一组元素组成的实体,包括程序代码和代码相关的数据集两个基本的元素。除此之外,因为进程之间会进行切换,因此进程中会有进程控制块。进程控制块里面包括每个进程的标识符、进程的状态、进程的优先级、程序计数器、内存指针、上下文数据、I/O状态信息、记账信息等。进程控制块的包含了充分的信息,因此在中断一个进程的执行,并且在后来恢复执行进程时就好像进程未被中断过。主要是因为进程被中断时,操作系统会把程序计数器和处理器寄存器(上下文数据)保存到进程控制块中的相应位置。

进程除了运行态之外,还有其他状态。当进程因为优先级过低被新排队的高优先级进程抢占CPU或者时间片用完或者进程内容已经执行完毕提前结束的时候,就会改变当前的运行态,转变为进程的其他状态。

进程三态状态转换图如上。操作系统可以任意创建进程,当进程处于新建态时,操作系统所需要的关于该进程的信息会保存在内存中的进程表中,但进程自身还未进入内存,进程中的程序保存在外存(通常是磁盘)中,操作系统也没有为这个程序相关的数据分配空间;当进程处于就绪态的时候,程序已经被写入内存,进程在队列中进行排队,通常会根据进程优先级、先进先出等规则等待获取CPU的时间片进入运行态;当进程因为等待其他未完成的操作,比如I/O操作、进程间在相互通信当前进程需要等待另一个进程提供输入或者等待来自另一个进程的信息时的时候,会进入阻塞态,此时已经归还时间片。当操作等待完成,会重新进入就绪态,在队列中继续排队;同时,进程获取的时间片已经用完,但还未执行完毕时,也会重新进入就绪态;只有当进程执行完毕,才会释放资源,退出状态。此时,该进程将从系统中删除。

线程是在进程中存在的更小的运行单元,当线程的概念引入进来之后,进程中的所有线程共享该进程的状态和资源,它们驻留在同一块地址空间中,并且可以访问到相同的数据。当一个线程改变了内存中的一个数据项时,其他线程在访问这一数据项时能够看到变化后的结果。如果一个线程以读权限打开一个文件,那么同一个进程中的其他线程也能够从这个文件中读取数据。除此之外,每个线程有独立的线程执行状态、执行栈、用于每个线程局部变量的静态存储空间等信息。

引入线程有很多优点。在一个已有进程中创建一个新线程比创建一个全新进程所需要的时间要少许多;终止一个线程比终止一个进程花费的时间少;同一进程内线程间切换比进程间切换花费的时间少;线程提高了不同的执行程序间通信的效率。在大多数操作系统中,独立进程间的通信需要内核的介入,以提供保护和通信所需要的机制。但是,由于在同一个进程中的线程共享内存和文件,它们无需调用内核就可以互相通信;

在Java语言中,开启一个新线程有四种方式:

(1)继承Thread类,编写run()方法;

(2)实现Runnable接口,实现run()方法;

(3)实现Callable接口,实现call()方法;

(4)开启线程池,加入实现了Runnable或者Callable接口的类;

代码如下:

import java.util.concurrent.*;


/*
    多线程实现方式一:继承Thread类,编写run()方法
 */
class Thread_one extends Thread {
    public void run() {
        super.run();
        System.out.println("Thread one run");
    }
}


/*
    多线程实现方式二:实现Runnable接口,实现run()方法
 */
class Thread_two implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread two run");
    }
}


/*
    多线程实现方式三:实现Callable接口,实现call()方法
 */
class Thread_three implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("Thread three run");
        return null;
    }
}


/*
    多线程实现方式四:通过线程池创建线程,Thread_four_Runnable实现Runnable接口,Thread_four_Callable实现Callable接口
 */
class Thread_four_Runnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread four Runnable Impl run");
    }
}


class Thread_four_Callable implements Callable<Object> {
    @Override
    public Integer call() throws Exception {
        System.out.println("Thread four Callable Impl run");
        return null;
    }
}


public class ThreadImpl {


    public static void main(String[] args) {


        Thread_one thread_one = new Thread_one();
        thread_one.start();


        Thread_two thread_two = new Thread_two();
        Thread thread = new Thread(thread_two);
        thread.start();


        /*
          由Callable<Integer>创建一个FutureTask<Integer>对象;
          再由FutureTask<Integer>创建一个Thread对象;
          说明:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,
               它同时实现了Future和Runnable接口。
         */
        Thread_three thread_three = new Thread_three();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(thread_three);
        Thread thread1 = new Thread(futureTask);
        thread1.start();


        //开启线程池,指定线程个数为1
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        Thread_four_Runnable thread_four_RunnableImpl = new Thread_four_Runnable();
        Thread_four_Callable thread_four_CallableImpl = new Thread_four_Callable();
        //把实现了Runnable的类加入线程池,使用execute()方法
        executorService.execute(thread_four_RunnableImpl);
        //把实现了Callable的类加入线程池,使用submit()方法
        executorService.submit(thread_four_CallableImpl);
        //关闭线程池
        executorService.shutdown();


        /*
            睡眠2秒钟,保证上述四种多线程开启方式都已执行完毕再继续执行下面的main主线程程序
         */
        try { TimeUnit.SECONDS.sleep(2);} catch (Exception e) {e.printStackTrace();}


        System.out.println("运行结束");
    }
}

执行结果如下

Thread one run
Thread four Runnable Impl run
Thread four Callable Impl run
Thread two run
Thread three run
运行结束
发布了622 篇原创文章 · 获赞 150 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/feizaoSYUACM/article/details/104574397