美文网首页FS全栈计划Java 杂谈
从0开始学线程并发(一)

从0开始学线程并发(一)

作者: MaxZing | 来源:发表于2019-03-12 16:33 被阅读0次

    什么是多线程

    进程:Process,系统级别的资源调度单位。相当于一个程序实例

    线程:Thread,进程内的资源调度单位,在进程内运行的最小单位,有自己的计数器和内存堆栈结构。

    多线程的好处

    1. 多核处理器资源利用更加充分
    2. 使程序响应时间更快
    3. 构建更好的编程模型

    一个线程的生命周期

    下图一共7个状态,创建预备运行定时等待等待阻塞终止
    而其他书上有简略版的,如:

    这些生命周期的状态在Java里就是对应线程的六个状态

    摘自《Java并发编程的艺术》

    线程从创建到结束

    1. 线程的创建

    // 直接new,或者创建Thread的子类(我用匿名方式替代了一下)
    Thread t = new Thread(){
        @Override
        public void run() {
            super.run();
        }
    };
    t.start();
    
    // 用 Runnable (我用lambda替代了一下)
    Thread t = new Thread(() -> System.out.println("new t"));
    t.start();
    
    // 用Timmer(其实是定时任务,在另一个线程中)
    Timer t = new Timer();
    t.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println(Instant.now());
        }
    }, 1000, 1000);
    
    
    // Future来包装Callable
    ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 1, 1L, TimeUnit.MINUTES,
            new ArrayBlockingQueue<Runnable>(1), new ThreadPoolExecutor.DiscardPolicy());
    System.out.println(Thread.currentThread().getName());
    try {
        Future t = executorService.submit(() -> Thread.currentThread().getName());
        System.out.println(t.get());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    

    还有线程池,上面Future就是使用线程池的,线程池一般很少创建单线程的,除非业务需要,所以下回再说,写个demo

    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(() -> System.out.println(Thread.currentThread().getName()));
    

    最为传统的方法就是new Thread,但是这种用法在大型软件开发中几乎不用,而是根据线程模型选择Future或者线程池去执行异步任务。这里的例子仅为展示线程的创建方法

    2. 线程的终止
    当线程逻辑运行完成后会自动退出。
    但是如果线程执行过程中,某些条件不满足,导致线程等待或者阻塞,就可能会导致异常终止。

    suspendresumestop被废弃了,原因是可能造成死锁,数据异常等问题。想要安全退出线程,可以使用中断请求标记来检查线程状态,检查到中断信号后,处理完数据、释放锁,再退出线程即可。

    3. 中断
    当线程的interrupt方法被其他线程调用的时候,这个线程就会接收到中断请求,如果线程自己检查isInterruted检查中断状态,也可以使用Thread.interrupted()静态方法恢复中断状态。
    许多抛InterruptedException的方法就是接受到中断请求,一般情况下会清除该线程中断标记,再抛出异常。

    线程的类别、属性等参数(优先级,状态)

    创建预备运行定时等待等待阻塞终止。其中预备和运行都被Java定义为RUNABLE状态

    线程的生命周期
    状态名称 说明
    NEW 初始状态,线程被构建,但是还没有调用 start() 方法
    RUNABLE 运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”
    BLOCKED 阻塞状态,表示线程阻塞于锁
    WAITING 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断)
    TIME_WAITING 超时等待状态,不同于WAITING,它是可以在指定时间内自行返回的
    TERMINATED 终止状态,表示当前线程已经执行完毕

    线程分类方式有很多种,除了前面创建方式分类其实还有一种分类方式

    Daemon线程和非Daemon线程
    Thread直接new的线程可以直接调用setDaemon (true)将这个线程设为守护线程。设置为守护线程后线程将会随虚拟机一直在幕后工作,前台是基本观察不到的。除非手动关闭,否则直到JVM准备关闭时,这个线程才会随之一同终止。

    相关文章

      网友评论

        本文标题:从0开始学线程并发(一)

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