美文网首页
java并发编程(一) 进程和线程

java并发编程(一) 进程和线程

作者: 卡戎li | 来源:发表于2020-05-05 00:48 被阅读0次

    一、进程与线程

    1.1 进程

    进程: 是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命周期。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消。反映了一个程序在一定的数据 集上运行的全部动态过程。通过进程控制块(PCB)唯一的标识某个进程。同时进程占据着相应的资源(例如包括cpu的使用 ,轮转时间以及一些其它设备的权限)。

    是系统进行资源分配和调度的一个独立单位。

    1.2 线程

    一个进程可以分为一到多个线程
    一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行。
    JAVA中,线程作为最小的调度单位,进程作为资源分配的最小单位。在windows中进程是不活动的,只是作为线程的容器。

    1.3 进程和线程对比

    图片.png

    二、并行和并发、同步和异步、阻塞和非阻塞

    2.1 并行和并发

    并发:一个处理器可以同时处理多个任务。这是逻辑上的同时发生。
    即:同一时间可以应对多个任务的能力。

    并行:多个处理器同时处理多个不同的任务。这是物理上的同时发生。
    即:同一时间可以同时做多个任务的能力。

    有一个清晰地比喻:
    并发:一个人同时吃三个苹果。并行:三个人同时吃三个苹果。

    • 并发(concurrency)


      图片.png
    • 并行(parallel)


      图片.png

    2.2 、同步和异步

    同步:需要等待结果返回,才能继续运行。

    异步:无需等待结果返回,就能继续运行。

    同步就是烧开水,需要自己去轮询(每隔一段时间去看看水开了没),异步就是水开了,然后水壶会通知你水已经开了,你可以回来处理这些开水了。
    同步和异步是相对于操作结果来说,会不会等待结果返回。

    2.3、阻塞和非阻塞

    阻塞就是线程在执行过程中不可以做其它的事情,非阻塞就是线程在执行中可以做其它的事情。

    • 阻塞举例
      顺序开会,一场会开完才能开另一场会。

    • 非阻塞举例
      一边打印文件一边听歌。

    三、通过继承Thread或实现Runnable 接口创建线程

    3.1 直接重写Thread的run 方法

    • demo01 创建Thread
    @Slf4j
    public class CreateThread {
    
        public static void main(String[] args) {
    
            method01();
            method02();
            log.info("thread is running");
        }
    
        public static void method01(){
            Thread thread = new Thread(){
    
                @Override
                public void run(){
                    log.info(" running");
                }
            };
            thread.setName("th01");
            thread.start();
        }
    
        public static void method02(){
            Thread thread = new Thread(() -> log.info(" running"));
            thread.setName("th02");
            thread.start();
        }
    }
    

    3.2 自定义类实现实现Runnable 接口

    @Slf4j
    public class JeffRunnable implements Runnable {
    
        private int ticket = 5;
    
        @Override
        public void run() {
            while (true) {
                log.info("Thread ticket = {}", ticket--);
                if (ticket < 0) {
                    break;
                }
            }
            log.info("my thread is running");
        }
    
        public static void main(String[] args) {
            JeffRunnable myThread = new JeffRunnable();
            Thread thread01 = new Thread(myThread);
            Thread thread02 = new Thread(myThread);
            thread01.setName("my thread 01");
            thread02.setName("my thread 02");
            thread01.start();
            thread02.start();
        }
    }
    
    00:10:07.666 [my thread 01] INFO com.learn.thread.learn01.MyThread - Thread ticket = 5
    00:10:07.666 [my thread 02] INFO com.learn.thread.learn01.MyThread - Thread ticket = 4
    00:10:07.679 [my thread 02] INFO com.learn.thread.learn01.MyThread - Thread ticket = 2
    00:10:07.679 [my thread 01] INFO com.learn.thread.learn01.MyThread - Thread ticket = 3
    00:10:07.679 [my thread 02] INFO com.learn.thread.learn01.MyThread - Thread ticket = 1
    00:10:07.679 [my thread 01] INFO com.learn.thread.learn01.MyThread - Thread ticket = 0
    00:10:07.679 [my thread 01] INFO com.learn.thread.learn01.MyThread - my thread is running
    00:10:07.679 [my thread 02] INFO com.learn.thread.learn01.MyThread - my thread is running
    

    3.3 Thread 和 Runnable接口的关系

    Thread有单继承的问题;
    Thread 本身也是实现了Runnable接口

    public
    class Thread implements Runnable {
        /* Make sure registerNatives is the first thing <clinit> does. */
        private static native void registerNatives();
        static {
            registerNatives();
        }
    
        private volatile String name;
        private int            priority;
        private Thread         threadQ;
        private long           eetop;
    

    四、通过Callable、Future和FutureTask 创建线程

    4.1 Callable

    • Callable 是一个接口,含有一个带返回值的call 方法
    @FunctionalInterface
    public interface Callable<V> {
        /**
         * Computes a result, or throws an exception if unable to do so.
         *
         * @return computed result
         * @throws Exception if unable to compute a result
         */
        V call() throws Exception;
    }
    
    

    4.2 Future

    Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

    • Future 也是一个接口,定义了6个方法
    public interface Future<V> {
         //方法用来取消任务
        boolean cancel(boolean mayInterruptIfRunning);
        //方法表示任务是否被取消成功
        boolean isCancelled();
        // 方法表示任务是否已经完成
        boolean isDone();
        // 方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
        V get() throws InterruptedException, ExecutionException;
        //用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    

    也就是说Future提供了三种功能:
    1)判断任务是否完成;
    2)能够中断任务;
    3)能够获取任务执行结果。

    因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

    4.3 FutureTask

    FutureTask 通过 RunnableFuture 间接实现了Runnable 和 Future

    public class FutureTask<V> implements RunnableFuture<V> {
    
    public interface RunnableFuture<V> extends Runnable, Future<V> {
        /**
         * Sets this Future to the result of its computation
         * unless it has been cancelled.
         */
        void run();
    }
    
    
    • FutureTask 两个构造函数,既可以处理callable,又可以处理runnable
     public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
    
    
     public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW;       // ensure visibility of callable
        }
    

    4.4 代码示例

    @Slf4j
    public class JeffCallable implements Callable<Integer> {
    
        private int ticket = 5;
    
        @Override
        public Integer call() {
            ticket--;
            log.info("Thread ticket = {}", ticket);
            return ticket;
        }
    
        public static void main(String[] args) {
            //创建callable对象
            JeffCallable call=new JeffCallable();
            FutureTask<Integer> futureTask=new FutureTask<Integer>(call);
            Thread thread=new Thread(futureTask,"th01");
            thread.start();
            //得到返回值
            try {
               log.info("返回值是:{}",  futureTask.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:java并发编程(一) 进程和线程

          本文链接:https://www.haomeiwen.com/subject/eftughtx.html